Skip to content

Commit

Permalink
Scripts: Scan block.json files to detect entry points in the build …
Browse files Browse the repository at this point in the history
…process
  • Loading branch information
gziolo committed Jan 11, 2022
1 parent d7c7af3 commit e533e67
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 28 deletions.
1 change: 1 addition & 0 deletions packages/scripts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Added a new `plugin-zip` command to create a zip file for a WordPress plugin ([#37687](https://github.com/WordPress/gutenberg/pull/37687)).
- Added optional support for React Fast Refresh in the `start` command. It can be activated with `--hot` CLI argument ([#28273](https://github.com/WordPress/gutenberg/pull/28273)).
- Automatically copy `block.json` files located in the `src` folder and its subfolders to the output folder (`build` by default) ([#37612](https://github.com/WordPress/gutenberg/pull/37612)).
- Scan the `src` directory for `block.json` files to detect defined scripts to use them as entry points with the `start` and `build` commands. ([#37661](https://github.com/WordPress/gutenberg/pull/37661)).

### Bug Fixes

Expand Down
9 changes: 5 additions & 4 deletions packages/scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ We commit to keeping the breaking changes minimal so you can upgrade `@wordpress

### `build`

Transforms your code according the configuration provided so it’s ready for production and optimized for the best performance. The entry point for your project’s code should be located in `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`). The output generated will be written to `build/index.js`. This script exits after producing a single build. For incremental builds, better suited for development, see the [start](#start) script.
Transforms your code according the configuration provided so it’s ready for production and optimized for the best performance. The entry points for your project get detected by scanning all script fields in `block.json` files located in the `src` directory. The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found. The output generated will be written to `build/index.js`. This script exits after producing a single build. For incremental builds, better suited for development, see the [start](#start) script.

_Example:_

Expand Down Expand Up @@ -334,7 +334,7 @@ It reuses the same logic as `npm pack` command to create an npm package tarball.

### `start`

Transforms your code according the configuration provided so it’s ready for development. The script will automatically rebuild if you make changes to the code, and you will see the build errors in the console. The entry point for your project’s code should be located in `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`). The output generated will be written to `build/index.js`. For single builds, better suited for production, see the [build](#build) script.
Transforms your code according the configuration provided so it’s ready for development. The script will automatically rebuild if you make changes to the code, and you will see the build errors in the console. The entry points for your project get detected by scanning all script fields in `block.json` files located in the `src` directory. The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found. The output generated will be written to `build/index.js`. For single builds, better suited for production, see the [build](#build) script.

_Example:_

Expand Down Expand Up @@ -527,13 +527,14 @@ The `build` and `start` commands use [webpack](https://webpack.js.org/) behind t

`@wordpress/scripts` bundles the default webpack config used as a base by the WordPress editor. These are the defaults:

- [Entry](https://webpack.js.org/configuration/entry-context/#entry): `src/index.js`
- [Output](https://webpack.js.org/configuration/output): `build/index.js`
- [Entry](https://webpack.js.org/configuration/entry-context/#entry): the entry points for your project get detected by scanning all script fields in `block.json` files located in the `src` directory. The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found.
- [Output](https://webpack.js.org/configuration/output): `build/[name].js`, for example: `build/index.js`, or `build/my-block/index.js`.
- [Loaders](https://webpack.js.org/loaders/):
- [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) allows transpiling JavaScript and TypeScript files using Babel and webpack.
- [`@svgr/webpack`](https://www.npmjs.com/package/@svgr/webpack) and [`url-loader`](https://webpack.js.org/loaders/url-loader/) makes it possible to handle SVG files in JavaScript code.
- [`css-loader`](https://webpack.js.org/loaders/css-loader/) chained with [`postcss-loader`](https://webpack.js.org/loaders/postcss-loader/) and [sass-loader](https://webpack.js.org/loaders/sass-loader/) let webpack process CSS, SASS or SCSS files referenced in JavaScript files.
- [Plugins](https://webpack.js.org/configuration/plugins) (among others):
- [`CopyWebpackPlugin`](https://webpack.js.org/plugins/copy-webpack-plugin/) copies all `block.json` files discovered in the `src` directory to the build directory.
- [`MiniCssExtractPlugin`](https://webpack.js.org/plugins/mini-css-extract-plugin/) extracts CSS into separate files. It creates a CSS file per JavaScript entry point which contains CSS.
- [`@wordpress/dependency-extraction-webpack-plugin`](/packages/dependency-extraction-webpack-plugin/README.md) is used with the default configuration to ensure that WordPress provided scripts are not included in the built bundle.

Expand Down
2 changes: 1 addition & 1 deletion packages/scripts/config/jest-e2e.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const jestE2EConfig = {
),
reporters: [
'default',
path.join( __dirname, 'jest-github-actions-reporter.js' ),
path.join( __dirname, 'jest-github-actions-reporter', 'index.js' ),
],
setupFilesAfterEnv: [ 'expect-puppeteer' ],
testEnvironment: path.join( __dirname, 'jest-environment-puppeteer' ),
Expand Down
2 changes: 1 addition & 1 deletion packages/scripts/config/jest-unit.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const jestUnitConfig = {
preset: '@wordpress/jest-preset-default',
reporters: [
'default',
path.join( __dirname, 'jest-github-actions-reporter.js' ),
path.join( __dirname, 'jest-github-actions-reporter', 'index.js' ),
],
};

Expand Down
29 changes: 9 additions & 20 deletions packages/scripts/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ const { BundleAnalyzerPlugin } = require( 'webpack-bundle-analyzer' );
const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' );
const CopyWebpackPlugin = require( 'copy-webpack-plugin' );
const browserslist = require( 'browserslist' );
const { sync: glob } = require( 'fast-glob' );
const MiniCSSExtractPlugin = require( 'mini-css-extract-plugin' );
const path = require( 'path' );
const { basename, dirname, resolve } = require( 'path' );
const ReactRefreshWebpackPlugin = require( '@pmmmwh/react-refresh-webpack-plugin' );
const TerserPlugin = require( 'terser-webpack-plugin' );

Expand All @@ -25,6 +24,7 @@ const {
hasBabelConfig,
hasCssnanoConfig,
hasPostCSSConfig,
getWebpackEntryPoints,
} = require( '../utils' );

const isProduction = process.env.NODE_ENV === 'production';
Expand All @@ -33,20 +33,6 @@ let target = 'browserslist';
if ( ! browserslist.findConfig( '.' ) ) {
target += ':' + fromConfigRoot( '.browserslistrc' );
}
let entry = {};
if ( process.env.WP_ENTRY ) {
entry = JSON.parse( process.env.WP_ENTRY );
} else {
// The script checks whether standard file names can be detected in the `src` folder,
// and converts all found files to entry points.
const entryFiles = glob( 'src/index.[jt]s?(x)', {
absolute: true,
} );
entryFiles.forEach( ( filepath ) => {
const [ entryName ] = path.basename( filepath ).split( '.' );
entry[ entryName ] = filepath;
} );
}

const cssLoaders = [
{
Expand Down Expand Up @@ -98,10 +84,10 @@ const cssLoaders = [
const config = {
mode,
target,
entry,
entry: getWebpackEntryPoints(),
output: {
filename: '[name].js',
path: path.resolve( process.cwd(), 'build' ),
path: resolve( process.cwd(), 'build' ),
},
resolve: {
alias: {
Expand All @@ -119,8 +105,11 @@ const config = {
test: /[\\/]style(\.module)?\.(sc|sa|c)ss$/,
chunks: 'all',
enforce: true,
name( module, chunks, cacheGroupKey ) {
return `${ cacheGroupKey }-${ chunks[ 0 ].name }`;
name( _, chunks, cacheGroupKey ) {
const chunkName = chunks[ 0 ].name;
return `${ dirname(
chunkName
) }/${ cacheGroupKey }-${ basename( chunkName ) }`;
},
},
default: false,
Expand Down
81 changes: 80 additions & 1 deletion packages/scripts/utils/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* External dependencies
*/
const { basename } = require( 'path' );
const { basename, dirname, join } = require( 'path' );
const { sync: glob } = require( 'fast-glob' );

/**
* Internal dependencies
Expand Down Expand Up @@ -164,9 +165,87 @@ const getWebpackArgs = () => {
return webpackArgs;
};

/**
* Detects the list of entry points to use with webpack. There are three ways to do this:
* 1. Use the legacy webpack 4 format passed as CLI arguments.
* 2. Scan `block.json` files for scripts.
* 3. Fallback to `src/index.*` file.
*
* @see https://webpack.js.org/concepts/entry-points/
*
* @return {Object<string,string>} The list of entry points.
*/
function getWebpackEntryPoints() {
// 1. Handles the legacy format for entry points when explicitly provided with the `process.env.WP_ENTRY`.
if ( process.env.WP_ENTRY ) {
return JSON.parse( process.env.WP_ENTRY );
}

// 2. Checks whether any block metadata files can be detected in the `src` directory.
// It scans all discovered files looking for JavaScript assets and converts them to entry points.
const blockMetadataFiles = glob( 'src/**/block.json', {
absolute: true,
} );
if ( blockMetadataFiles.length > 0 ) {
return blockMetadataFiles.reduce(
( accumulator, blockMetadataFile ) => {
const {
editorScript,
script,
viewScript,
} = require( blockMetadataFile );
[ editorScript, script, viewScript ]
.flat()
.filter( ( value ) => value && value.startsWith( 'file:' ) )
.forEach( ( value ) => {
// Removes the `file:` prefix.
const filepath = join(
dirname( blockMetadataFile ),
value.replace( 'file:', '' )
);

// Takes the path without the file extension, and relative to the `src` directory.
const [ , entryName ] = filepath
.split( '.' )[ 0 ]
.split( 'src/' );
if ( ! entryName ) {
return;
}

// Detects the proper file extension used in the `src` directory.
const [ entryFilepath ] = glob(
`src/${ entryName }.[jt]s?(x)`,
{
absolute: true,
}
);

accumulator[ entryName ] = entryFilepath;
} );
return accumulator;
},
{}
);
}

// 3. Checks whether a standard file name can be detected in the `src` directory,
// and converts the discovered file to entry point.
const [ entryFile ] = glob( 'src/index.[jt]s?(x)', {
absolute: true,
} );
if ( ! entryFile ) {
return {};
}

return {
index: entryFile,
};
}

module.exports = {
getJestOverrideConfigFile,
getWebpackArgs,
getWebpackEntryPoints,
hasBabelConfig,
hasCssnanoConfig,
hasJestConfig,
Expand Down
2 changes: 2 additions & 0 deletions packages/scripts/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
const {
getJestOverrideConfigFile,
getWebpackArgs,
getWebpackEntryPoints,
hasBabelConfig,
hasCssnanoConfig,
hasJestConfig,
Expand All @@ -32,6 +33,7 @@ module.exports = {
getNodeArgsFromCLI,
getPackageProp,
getWebpackArgs,
getWebpackEntryPoints,
hasArgInCLI,
hasBabelConfig,
hasCssnanoConfig,
Expand Down
2 changes: 1 addition & 1 deletion test/unit/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ module.exports = {
],
reporters: [
'default',
'<rootDir>packages/scripts/config/jest-github-actions-reporter.js',
'<rootDir>packages/scripts/config/jest-github-actions-reporter/index.js',
],
};

0 comments on commit e533e67

Please sign in to comment.