Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripts: Add new flag to allow customization of the src directory. #39618

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/scripts/CHANGELOG.md
Expand Up @@ -2,10 +2,15 @@

## Unreleased

### Bug Fix
### New Feature

- Add `--webpack-src-dir` CLI flag to allow customizing the source code directory (`src` by default) ([#39618](https://github.com/WordPress/gutenberg/pull/39618)).

### Bug Fixes

- Add `vendor/` to `.markdownlintignore`, to match `lint-md-docs` docs ([#39724](https://github.com/WordPress/gutenberg/pull/39724)).
- Include files with `.jsx` extension in the build process ([#39613](https://github.com/WordPress/gutenberg/pull/39613)).
- Ensure that the default logic for entry points in the build commands is executed only when used the default config ([#39618](https://github.com/WordPress/gutenberg/pull/39618)).

## 22.2.0 (2022-03-11)

Expand Down
19 changes: 15 additions & 4 deletions packages/scripts/README.md
Expand Up @@ -47,6 +47,10 @@ _Example:_

It might also be a good idea to get familiar with the [JavaScript Build Setup tutorial](https://github.com/WordPress/gutenberg/tree/HEAD/docs/how-to-guides/javascript/js-build-setup.md) for setting up a development environment to use ESNext syntax. It gives a very in-depth explanation of how to use the [build](#build) and [start](#start) scripts.

## Automatic block.json detection and the source code directory
When using the `start` or `build` commands, the source code directory ( the default is `./src`) and its subdirectories are scanned for the existence of `block.json` files. If one or more are found, they are treated a entry points and will be output into corresponding folders in the `build` directory. The allows for the creation of multiple blocks that use a single build process. The source directory can be customized using the `--webpack-src-dir` flag.


## Updating to New Release

To update an existing project to a new version of `@wordpress/scripts`, open the [changelog](https://github.com/WordPress/gutenberg/blob/HEAD/packages/scripts/CHANGELOG.md), find the version you’re currently on (check `package.json` in the top-level directory of your project), and apply the migration instructions for the newer versions.
Expand All @@ -55,6 +59,7 @@ In most cases bumping the `@wordpress/scripts` version in `package.json` and run

We commit to keeping the breaking changes minimal so you can upgrade `@wordpress/scripts` as seamless as possible.


## Available Scripts

### `build`
Expand All @@ -80,7 +85,8 @@ _Example:_
"scripts": {
"build": "wp-scripts build",
"build:custom": "wp-scripts build entry-one.js entry-two.js --output-path=custom",
"build:copy-php": "wp-scripts build --webpack-copy-php"
"build:copy-php": "wp-scripts build --webpack-copy-php",
"build:custom-directory": "wp-scripts build --webpack-src-dir=custom-directory"
}
}
```
Expand All @@ -90,12 +96,14 @@ This is how you execute the script with presented setup:
- `npm run build` - builds the code for production.
- `npm run build:custom` - builds the code for production with two entry points and a custom output directory. Paths for custom entry points are relative to the project root.
- `npm run build:copy-php` - builds the code for production and opts into copying PHP files from the `src` directory and its subfolders to the output directory.
- `build:custom-directory` - builds the code for production using the `custom-directory` as the source code directory.

This script automatically use the optimized config but sometimes you may want to specify some custom options:

- `--webpack-bundle-analyzer` – enables visualization for the size of webpack output files with an interactive zoomable treemap.
- `--webpack-copy-php` – enables copying PHP files from the `src` directory and its subfolders to the output directory.
- `--webpack-copy-php` – enables copying PHP files from the source directory ( default is `src` ) and its subfolders to the output directory.
- `--webpack-no-externals` – disables scripts' assets generation, and omits the list of default externals.
- `--webpack-src-dir` – Allows customization of the source code directory. Default is `src`.

#### Advanced information

Expand Down Expand Up @@ -371,7 +379,8 @@ _Example:_
"start": "wp-scripts start",
"start:hot": "wp-scripts start --hot",
"start:custom": "wp-scripts start entry-one.js entry-two.js --output-path=custom",
"start:copy-php": "wp-scripts start"
"start:copy-php": "wp-scripts start --webpack-copy-php",
"start:custom-directory": "wp-scripts start --webpack-src-dir=custom-directory",
}
}
```
Expand All @@ -382,14 +391,16 @@ This is how you execute the script with presented setup:
- `npm run start:hot` - starts the build for development with "Fast Refresh". The page will automatically reload if you make changes to the files.
- `npm run start:custom` - starts the build for development which contains two entry points and a custom output directory. Paths for custom entry points are relative to the project root.
- `npm run start:copy-php` - starts the build for development and opts into copying PHP files from the `src` directory and its subfolders to the output directory.
- `npm run start:custom-directory` - builds the code for production using the `custom-directory` as the source code directory.

This script automatically use the optimized config but sometimes you may want to specify some custom options:

- `--hot` – enables "Fast Refresh". The page will automatically reload if you make changes to the code. _For now, it requires that WordPress has the [`SCRIPT_DEBUG`](https://wordpress.org/support/article/debugging-in-wordpress/#script_debug) flag enabled and the [Gutenberg](https://wordpress.org/plugins/gutenberg/) plugin installed._
- `--webpack-bundle-analyzer` – enables visualization for the size of webpack output files with an interactive zoomable treemap.
- `--webpack-copy-php` – enables copying PHP files from the `src` directory and its subfolders to the output directory.
- `--webpack-copy-php` – enables copying PHP files from the source directory ( default is `src` ) and its subfolders to the output directory.
- `--webpack-devtool` – controls how source maps are generated. See options at https://webpack.js.org/configuration/devtool/#devtool.
- `--webpack-no-externals` – disables scripts' assets generation, and omits the list of default externals.
- `--webpack-src-dir` – Allows customization of the source code directory. Default is `src`.

#### Advanced information

Expand Down
8 changes: 4 additions & 4 deletions packages/scripts/config/webpack.config.js
Expand Up @@ -36,7 +36,7 @@ if ( ! browserslist.findConfig( '.' ) ) {
}
const hasReactFastRefresh = hasArgInCLI( '--hot' ) && ! isProduction;

const copyWebPackPatterns = process.env.WP_COPY_PHP_FILES_TO_DIST
const copyWebpackPatterns = process.env.WP_COPY_PHP_FILES_TO_DIST
? '**/{block.json,*.php}'
: '**/block.json';

Expand Down Expand Up @@ -90,7 +90,7 @@ const cssLoaders = [
const config = {
mode,
target,
entry: getWebpackEntryPoints(),
entry: getWebpackEntryPoints,
output: {
filename: '[name].js',
path: resolve( process.cwd(), 'build' ),
Expand Down Expand Up @@ -232,8 +232,8 @@ const config = {
new CopyWebpackPlugin( {
patterns: [
{
from: copyWebPackPatterns,
context: 'src',
from: copyWebpackPatterns,
context: process.env.WP_SRC_DIRECTORY,
noErrorOnMissing: true,
},
],
Expand Down
6 changes: 5 additions & 1 deletion packages/scripts/scripts/build.js
Expand Up @@ -7,7 +7,7 @@ const { sync: resolveBin } = require( 'resolve-bin' );
/**
* Internal dependencies
*/
const { getWebpackArgs, hasArgInCLI } = require( '../utils' );
const { getWebpackArgs, hasArgInCLI, getArgFromCLI } = require( '../utils' );

process.env.NODE_ENV = process.env.NODE_ENV || 'production';

Expand All @@ -23,6 +23,10 @@ if ( hasArgInCLI( '--webpack-copy-php' ) ) {
process.env.WP_COPY_PHP_FILES_TO_DIST = true;
}

process.env.WP_SRC_DIRECTORY = hasArgInCLI( '--webpack-src-dir' )
? getArgFromCLI( '--webpack-src-dir' )
: 'src';

const { status } = spawn( resolveBin( 'webpack' ), getWebpackArgs(), {
stdio: 'inherit',
} );
Expand Down
4 changes: 4 additions & 0 deletions packages/scripts/scripts/start.js
Expand Up @@ -25,6 +25,10 @@ if ( hasArgInCLI( '--webpack-copy-php' ) ) {
process.env.WP_COPY_PHP_FILES_TO_DIST = true;
}

process.env.WP_SRC_DIRECTORY = hasArgInCLI( '--webpack-src-dir' )
? getArgFromCLI( '--webpack-src-dir' )
: 'src';

const { status } = spawn(
resolveBin( 'webpack' ),
[ hasArgInCLI( '--hot' ) ? 'serve' : 'watch', ...getWebpackArgs() ],
Expand Down
62 changes: 40 additions & 22 deletions packages/scripts/utils/config.js
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
const chalk = require( 'chalk' );
const { readFileSync } = require( 'fs' );
const { basename, dirname, extname, join, sep } = require( 'path' );
const { sync: glob } = require( 'fast-glob' );

Expand Down Expand Up @@ -183,26 +184,34 @@ function getWebpackEntryPoints() {
return JSON.parse( process.env.WP_ENTRY );
}

// Continue only if the `src` directory exists.
if ( ! hasProjectFile( 'src' ) ) {
// Continue only if the source directory exists.
if ( ! hasProjectFile( process.env.WP_SRC_DIRECTORY ) ) {
log(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember some folks reporting a similar message on the terminal was confusing in case they using a custom config that overrides the entry points.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It made me think that we could use a dynamic entry as documented in https://webpack.js.org/configuration/entry-context/#dynamic-entry. We would never run this code when the project overrides entry points.

If a function is passed, then it will be invoked on every make event.

Note that the making event triggers when webpack starts and for every invalidation when watching for file changes.

In fact, this would solve a more pressing issue we recently discovered with @schmitzoide when working on a plugin with multiple blocks. Currently, the logic for finding entry points runs only once in the watch mode. Therefore you need to restart the development build whenever new blocks get introduced or scripts for the block change. Using a callback function should resolve the issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related comment I mentioned: #38739 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gziolo @ryanwelcher Hope this PR resolves the confusing behaviour for #38739 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added commit 37ec581 to see if that resolves the issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that the message isn't shown when we use the default handling for entry points.

I can also confirm that entry points get dynamically updated in the watch mode when block.json changes.

chalk.yellow(
`Source directory "${ process.env.WP_SRC_DIRECTORY }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.`
)
);
return {};
}

// 2. Checks whether any block metadata files can be detected in the `src` directory.
// 2. Checks whether any block metadata files can be detected in the defined source directory.
// It scans all discovered files looking for JavaScript assets and converts them to entry points.
const blockMetadataFiles = glob( 'src/**/block.json', {
absolute: true,
} );
const blockMetadataFiles = glob(
`${ process.env.WP_SRC_DIRECTORY }/**/block.json`,
{
absolute: true,
}
);

if ( blockMetadataFiles.length > 0 ) {
const srcDirectory = fromProjectRoot( 'src' + sep );
const srcDirectory = fromProjectRoot(
process.env.WP_SRC_DIRECTORY + sep
);
const entryPoints = blockMetadataFiles.reduce(
( accumulator, blockMetadataFile ) => {
const {
editorScript,
script,
viewScript,
} = require( blockMetadataFile );
const { editorScript, script, viewScript } = JSON.parse(
readFileSync( blockMetadataFile )
);
[ editorScript, script, viewScript ]
.flat()
.filter( ( value ) => value && value.startsWith( 'file:' ) )
Expand All @@ -213,7 +222,7 @@ function getWebpackEntryPoints() {
value.replace( 'file:', '' )
);

// Takes the path without the file extension, and relative to the `src` directory.
// Takes the path without the file extension, and relative to the defined source directory.
if ( ! filepath.startsWith( srcDirectory ) ) {
log(
chalk.yellow(
Expand All @@ -223,7 +232,9 @@ function getWebpackEntryPoints() {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
) }". File is located outside of the "src" directory.`
) }". File is located outside of the "${
process.env.WP_SRC_DIRECTORY
}" directory.`
)
);
return;
Expand All @@ -233,9 +244,9 @@ function getWebpackEntryPoints() {
.replace( srcDirectory, '' )
.replace( /\\/g, '/' );

// Detects the proper file extension used in the `src` directory.
// Detects the proper file extension used in the defined source directory.
const [ entryFilepath ] = glob(
`src/${ entryName }.[jt]s?(x)`,
`${ process.env.WP_SRC_DIRECTORY }/${ entryName }.[jt]s?(x)`,
{
absolute: true,
}
Expand All @@ -250,7 +261,9 @@ function getWebpackEntryPoints() {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
) }". File does not exist in the "src" directory.`
) }". File does not exist in the "${
process.env.WP_SRC_DIRECTORY
}" directory.`
)
);
return;
Expand All @@ -267,14 +280,19 @@ function getWebpackEntryPoints() {
}
}

// 3. Checks whether a standard file name can be detected in the `src` directory,
// 3. Checks whether a standard file name can be detected in the defined source directory,
// and converts the discovered file to entry point.
const [ entryFile ] = glob( 'src/index.[jt]s?(x)', {
absolute: true,
} );
const [ entryFile ] = glob(
`${ process.env.WP_SRC_DIRECTORY }/index.[jt]s?(x)`,
{
absolute: true,
}
);
if ( ! entryFile ) {
log(
chalk.yellow( 'No entry file discovered in the "src" directory.' )
chalk.yellow(
`No entry file discovered in the "${ process.env.WP_SRC_DIRECTORY }" directory.`
)
);
return {};
}
Expand Down