diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 42afdd02e0d605..9b15e111ee2764 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Enhancements + +- Recommend listing JavaScript entry points as paths passed to the `start` and `build` commands ([#68251](https://github.com/WordPress/gutenberg/pull/68251)). +- Introduce a new option `--source-path` to customize the source directory used with the `start` and `build` commands ([#68251](https://github.com/WordPress/gutenberg/pull/68251)). + ## 30.7.0 (2024-12-11) ### Internal diff --git a/packages/scripts/README.md b/packages/scripts/README.md index f86a4c6091c408..9a9ce1dc652a2f 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -46,10 +46,6 @@ _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. This 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 and the output directory with the `--output-path` 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. @@ -66,19 +62,7 @@ Transforms your code according the configuration provided so it’s ready for pr _This script exits after producing a single build. For incremental builds, better suited for development, see the [start](#start) script._ -The entry points for your project get detected by scanning all script fields in `block.json` files located in the `src` directory. The script fields in `block.json` should pass relative paths to `block.json` in the same folder. - -_Example:_ - -```json -{ - "editorScript": "file:index.js", - "script": "file:script.js", - "viewScript": "file:view.js" -} -``` - -The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found. In that scenario, the output generated will be written to `build/index.js`. +#### Usage _Example:_ @@ -88,7 +72,7 @@ _Example:_ "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:custom-directory": "wp-scripts build --webpack-src-dir=custom-directory" + "build:custom-directory": "wp-scripts build --source-path=custom-directory" } } ``` @@ -104,8 +88,8 @@ This script automatically use the optimized config but sometimes you may want to - `--webpack-bundle-analyzer` – enables visualization for the size of webpack output files with an interactive zoomable treemap. - `--webpack-copy-php` – enables copying all 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`. +- `--webpack-no-externals` – disables scripts’ assets generation, and omits the list of default externals. +- `--source-path` – Allows customization of the source directory. Default is `.`. In the automatic detection mode the default changes to `src`. - `--output-path` – Allows customization of the output directory. Default is `build`. Experimental support for the block.json `viewScriptModule` field is available via the @@ -113,11 +97,12 @@ Experimental support for the block.json `viewScriptModule` field is available vi compiled. The `viewScriptModule` field is analogous to the `viewScript` field, but will compile a module and should be registered in WordPress using the Modules API. +Learn more about [using build scripts](#using-build-scripts) to optimize the development experience based on your specific needs. + #### Advanced information This script uses [webpack](https://webpack.js.org/) behind the scenes. It’ll look for a webpack config in the top-level directory of your package and will use it if it finds one. If none is found, it’ll use the default config provided by `@wordpress/scripts` packages. Learn more in the [Advanced Usage](#advanced-usage) section. - ### `build-blocks-manifest` This script generates a PHP file containing block metadata from all @@ -128,10 +113,12 @@ when registering multiple block types, as it allows you to use Usage: `wp-scripts build-blocks-manifest [options]` Options: -- `--input`: Specify the input directory (default: 'build') -- `--output`: Specify the output file path (default: 'build/blocks-manifest.php') + +- `--input`: Specify the input directory (default: 'build') +- `--output`: Specify the output file path (default: 'build/blocks-manifest.php') Example: + ```bash wp-scripts build-blocks-manifest --input=src --output=dist/blocks-manifest.php ``` @@ -382,8 +369,8 @@ This is how you create a custom root folder inside the zip file. - When updating a plugin, WordPress expects a folder in the root of the zip file which matches the plugin name. So be aware that this may affect the plugin update process. - `--root-folder` - Add a custom root folder to the zip file. -- `npm run plugin-zip` - By default, unzipping your plugin's zip file will result in a folder with the same name as your plugin. -- `npm run plugin-zip --root-folder='custom-directory'` - Your plugin's zip file will be unzipped into a folder named `custom-directory`. +- `npm run plugin-zip` - By default, unzipping your plugin’s zip file will result in a folder with the same name as your plugin. +- `npm run plugin-zip --root-folder='custom-directory'` - Your plugin’s zip file will be unzipped into a folder named `custom-directory`. - `npm run plugin-zip --no-root-folder` - This will create a zip file that has no folder inside, your plugin files will be unzipped directly into the target directory. ### `start` @@ -392,19 +379,7 @@ Transforms your code according the configuration provided so it’s ready for de _For single builds, better suited for production, see the [build](#build) script._ -The entry points for your project get detected by scanning all script fields in `block.json` files located in the `src` directory. The script fields in `block.json` should pass relative paths to `block.json` in the same folder. - -_Example:_ - -```json -{ - "editorScript": "file:index.js", - "script": "file:script.js", - "viewScript": "file:view.js" -} -``` - -The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found. In that scenario, the output generated will be written to `build/index.js`. +#### Usage _Example:_ @@ -415,7 +390,7 @@ _Example:_ "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 --webpack-copy-php", - "start:custom-directory": "wp-scripts start --webpack-src-dir=custom-directory" + "start:custom-directory": "wp-scripts start --source-path=custom-directory" } } ``` @@ -435,8 +410,8 @@ This script automatically use the optimized config but sometimes you may want to - `--webpack-bundle-analyzer` – enables visualization for the size of webpack output files with an interactive zoomable treemap. - `--webpack-copy-php` – enables copying all 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`. +- `--webpack-no-externals` – disables scripts’ assets generation, and omits the list of default externals. +- `--source-path` – Allows customization of the source directory. Default is `.`. In the automatic detection mode the default changes to `src`. - `--output-path` – Allows customization of the output directory. Default is `build`. Experimental support for the block.json `viewScriptModule` field is available via the @@ -444,6 +419,8 @@ Experimental support for the block.json `viewScriptModule` field is available vi compiled. The `viewScriptModule` field is analogous to the `viewScript` field, but will compile a module and should be registered in WordPress using the Modules API. +Learn more about [using build scripts](#using-build-scripts) to optimize the development experience based on your specific needs. + #### Advanced information This script uses [webpack](https://webpack.js.org/) behind the scenes. It’ll look for a webpack config in the top-level directory of your package and will use it if it finds one. If none is found, it’ll use the default config provided by `@wordpress/scripts` packages. Learn more in the [Advanced Usage](#advanced-usage) section. @@ -492,7 +469,7 @@ We enforce that all tests run serially in the current process using [--runInBand When tests fail, both a screenshot and an HTML snapshot will be taken of the page and stored in the `artifacts/` directory at the root of your project. These snapshots may help debug failed tests during development or when running tests in a CI environment. -The `artifacts/` directory can be customized by setting the `WP_ARTIFACTS_PATH` environment variable to the relative path of the desired directory within your project's root. For example: to change the default directory from `artifacts/` to `my/custom/artifacts`, you could use `WP_ARTIFACTS_PATH=my/custom/artifacts npm run test:e2e`. +The `artifacts/` directory can be customized by setting the `WP_ARTIFACTS_PATH` environment variable to the relative path of the desired directory within your project’s root. For example: to change the default directory from `artifacts/` to `my/custom/artifacts`, you could use `WP_ARTIFACTS_PATH=my/custom/artifacts npm run test:e2e`. #### Advanced information @@ -581,11 +558,11 @@ To do so, you can add a file called `playwright.config.ts` or `playwright.config When tests fail, snapshots will be taken of the page and stored in the `artifacts/` directory at the root of your project. These snapshots may help debug failed tests during development or when running tests in a CI environment. -The `artifacts/` directory can be customized by setting the `WP_ARTIFACTS_PATH` environment variable to the relative path of the desired directory within your project's root. For example: to change the default directory from `artifacts/` to `my/custom/artifacts`, you could use `WP_ARTIFACTS_PATH=my/custom/artifacts npm run test:playwright`. +The `artifacts/` directory can be customized by setting the `WP_ARTIFACTS_PATH` environment variable to the relative path of the desired directory within your project’s root. For example: to change the default directory from `artifacts/` to `my/custom/artifacts`, you could use `WP_ARTIFACTS_PATH=my/custom/artifacts npm run test:playwright`. #### Advanced information -You are able to use all of Playwright's [CLI options](https://playwright.dev/docs/test-cli#reference). You can also run `./node_modules/.bin/wp-scripts test-playwright --help` or `npm run test:playwright:help` (as mentioned above) to view all the available options. Learn more in the [Advanced Usage](#advanced-usage) section. +You are able to use all of Playwright’s [CLI options](https://playwright.dev/docs/test-cli#reference). You can also run `./node_modules/.bin/wp-scripts test-playwright --help` or `npm run test:playwright:help` (as mentioned above) to view all the available options. Learn more in the [Advanced Usage](#advanced-usage) section. ## Passing Node.js options @@ -639,30 +616,47 @@ To also debug the browser context, run `wp-scripts --inspect-brk test-e2e --pupp For more e2e debugging tips check out the [Puppeteer debugging docs](https://developers.google.com/web/tools/puppeteer/debugging). -## Advanced Usage +## Using build scripts -In general, this package should be used with the set of recommended config files. While it’s possible to override every single config file provided, if you have to do it, it means that your use case is far more complicated than anticipated. If that happens, it would be better to avoid using the whole abstraction layer and set up your project with full control over tooling used. +The `build` and `start` commands use [webpack](https://webpack.js.org/) behind the scenes. webpack is used to bundle and optimize code for web applications, enabling developers to manage dependencies efficiently, enhance performance, and simplify the development workflow. -### Working with build scripts +### Listing entry points -The `build` and `start` commands use [webpack](https://webpack.js.org/) behind the scenes. webpack is a tool that helps you transform your code into something else. For example: it can take code written in ESNext and output ES5 compatible code that is minified for production. +The simplest way to list JavaScript entry points is to pass them as arguments for the command. -#### Default webpack config +_Example:_ -`@wordpress/scripts` bundles the default webpack config used as a base by the WordPress editor. These are the defaults: +```bash +wp-scripts build entry-one.js entry-two.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`](https://github.com/WordPress/gutenberg/tree/HEAD/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. +### Automatic block.json detection and the source code directory -#### Using CSS +A convenient alternative for blocks is using automatic entry point detection. In that case, 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, the JavaScript files listed in metadata are treated as entry points and will be output into corresponding folders in the `build` directory. The script fields in `block.json` should pass relative paths to `block.json` in the same folder. + +_Example:_ + +```json +{ + "editorScript": "file:index.js", + "script": "file:script.js", + "viewScript": "file:view.js" +} +``` + +This allows for the creation of multiple blocks that use a single build process triggered with a simple command: + +```bash +wp-scripts build +``` + +The source directory can be customized using the `--source-path` flag and the output directory with the `--output-path` flag. + +### Fallback entry point + +The fallback entry point is `src/index.js` (other supported extensions: `.jsx`, `.ts`, and `.tsx`) in case there is no `block.json` file found. In that scenario, the output generated will be written to `build/index.js`. + +### Importing styles in JavaScript _Example:_ @@ -694,19 +688,19 @@ When you run the build using the default command `wp-scripts build` (also applie 1. `index.css` – all imported CSS files are bundled into one chunk named after the entry point, which defaults to `index.js`, and thus the file created becomes `index.css`. This is for styles used only in the editor. 2. `style-index.css` – imported `style.css` file(s) (applies to PCSS, SASS and SCSS extensions) get bundled into one `style-index.css` file that is meant to be used both on the front-end and in the editor. -You can also have multiple entry points as described in the docs for the script: +For example, when the project has two entry points: ```bash -wp-scripts start entry-one.js entry-two.js --output-path=custom +wp-scripts build entry-one.js entry-two.js ``` -If you do so, then CSS files generated will follow the names of the entry points: `entry-one.css` and `entry-two.css`. +In that case, the CSS generated based on import statements in the JavaScript code will follow the names of the entry points: `entry-one.css` and `entry-two.css`. -Avoid using `style` keyword in an entry point name, this might break your build process. +_Important:_ Avoid using `style` keyword in an entry point name, this might break your build process. You can also bundle CSS modules by prefixing `.module` to the extension, e.g. `style.module.scss`. Otherwise, these files are handled like all other `style.scss`. They will also be extracted into `style-index.css`. -#### Using fonts and images +### Using fonts and images It is possible to reference font (`woff`, `woff2`, `eot`, `ttf` and `otf`) and image (`bmp`, `png`, `jpg`, `jpeg`, `gif` and `wepb`) files from CSS that is controlled by webpack as explained in the previous section. @@ -724,7 +718,7 @@ _Example:_ } ``` -#### Using SVG +### Using SVG _Example:_ @@ -739,18 +733,37 @@ const App = () => ( ); ``` -#### Provide your own webpack config +## Advanced Usage + +This package should generally be used with the set of recommended config files. While it’s possible to override every config file provided, if you have to do it, your use case is far more complicated than anticipated. If that happens, it would be better to avoid using the whole abstraction layer and set up your project with full control over the tooling used. + +### Default webpack config + +`@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): 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`](https://github.com/WordPress/gutenberg/tree/HEAD/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. + +### Provide your own webpack config Should there be any situation where you want to provide your own webpack config, you can do so. The `build` and `start` commands will use your provided file when: - the command receives a `--config` argument. Example: `wp-scripts build --config my-own-webpack-config.js`. - there is a file called `webpack.config.js` or `webpack.config.babel.js` in the top-level directory of your project (at the same level as `package.json`). -##### Extending the webpack config +#### Extending the webpack config To extend the provided webpack config, or replace subsections within the provided webpack config, you can provide your own `webpack.config.js` file, `require` the provided `webpack.config.js` file, and use the [`spread` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to import all of or part of the provided configuration. -In the example below, a `webpack.config.js` file is added to the root folder extending the provided webpack config to include custom logic to parse module's source and convert it to a JavaScript object using [`toml`](https://www.npmjs.com/package/toml). It may be useful to import toml or other non-JSON files as JSON, without specific loaders: +In the example below, a `webpack.config.js` file is added to the root folder extending the provided webpack config to include custom logic to parse module’s source and convert it to a JavaScript object using [`toml`](https://www.npmjs.com/package/toml). It may be useful to import toml or other non-JSON files as JSON, without specific loaders: ```javascript const toml = require( 'toml' ); @@ -781,8 +794,8 @@ If you follow this approach, please, be aware that: ## Contributing to this package -This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. +This is an individual package that’s part of the Gutenberg project. The project is organized as a monorepo. It’s made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects. -To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md). +To find out more about contributing to this package or Gutenberg as a whole, please read the project’s main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md).

Code is Poetry.

diff --git a/packages/scripts/config/webpack.config.js b/packages/scripts/config/webpack.config.js index 1829da5cdc15da..bfeb929f25ac61 100644 --- a/packages/scripts/config/webpack.config.js +++ b/packages/scripts/config/webpack.config.js @@ -29,7 +29,7 @@ const { hasArgInCLI, hasCssnanoConfig, hasPostCSSConfig, - getWordPressSrcDirectory, + getProjectSourcePath, getWebpackEntryPoints, getAsBooleanFromENV, getBlockJsonModuleFields, @@ -302,14 +302,14 @@ const scriptConfig = { } ), new PhpFilePathsPlugin( { - context: getWordPressSrcDirectory(), + context: getProjectSourcePath(), props: [ 'render', 'variations' ], } ), new CopyWebpackPlugin( { patterns: [ { from: '**/block.json', - context: getWordPressSrcDirectory(), + context: getProjectSourcePath(), noErrorOnMissing: true, transform( content, absoluteFrom ) { const convertExtension = ( path ) => { @@ -346,7 +346,7 @@ const scriptConfig = { const runtimePath = relative( dirname( absoluteFrom ), fromProjectRoot( - getWordPressSrcDirectory() + + getProjectSourcePath() + sep + 'runtime.js' ) @@ -375,7 +375,7 @@ const scriptConfig = { }, { from: '**/*.php', - context: getWordPressSrcDirectory(), + context: getProjectSourcePath(), noErrorOnMissing: true, filter: ( filepath ) => { return ( @@ -417,7 +417,7 @@ if ( hasExperimentalModulesFlag ) { /** @type {ReadonlyArray} */ this.blockJsonFiles = glob( '**/block.json', { absolute: true, - cwd: fromProjectRoot( getWordPressSrcDirectory() ), + cwd: fromProjectRoot( getProjectSourcePath() ), } ); } diff --git a/packages/scripts/scripts/build.js b/packages/scripts/scripts/build.js index 0eef2afb451bfc..8c7b768ba3e694 100644 --- a/packages/scripts/scripts/build.js +++ b/packages/scripts/scripts/build.js @@ -7,31 +7,11 @@ const { sync: resolveBin } = require( 'resolve-bin' ); /** * Internal dependencies */ -const { getWebpackArgs, hasArgInCLI, getArgFromCLI } = require( '../utils' ); +const { getWebpackArgs } = require( '../utils' ); const EXIT_ERROR_CODE = 1; process.env.NODE_ENV = process.env.NODE_ENV || 'production'; -if ( hasArgInCLI( '--experimental-modules' ) ) { - process.env.WP_EXPERIMENTAL_MODULES = true; -} - -if ( hasArgInCLI( '--webpack-no-externals' ) ) { - process.env.WP_NO_EXTERNALS = true; -} - -if ( hasArgInCLI( '--webpack-bundle-analyzer' ) ) { - process.env.WP_BUNDLE_ANALYZER = true; -} - -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', } ); diff --git a/packages/scripts/scripts/start.js b/packages/scripts/scripts/start.js index 6296192ef302b1..fd0a191f168e9e 100644 --- a/packages/scripts/scripts/start.js +++ b/packages/scripts/scripts/start.js @@ -7,33 +7,9 @@ const { sync: resolveBin } = require( 'resolve-bin' ); /** * Internal dependencies */ -const { getArgFromCLI, getWebpackArgs, hasArgInCLI } = require( '../utils' ); +const { getWebpackArgs, hasArgInCLI } = require( '../utils' ); const EXIT_ERROR_CODE = 1; -if ( hasArgInCLI( '--experimental-modules' ) ) { - process.env.WP_EXPERIMENTAL_MODULES = true; -} - -if ( hasArgInCLI( '--webpack-no-externals' ) ) { - process.env.WP_NO_EXTERNALS = true; -} - -if ( hasArgInCLI( '--webpack-bundle-analyzer' ) ) { - process.env.WP_BUNDLE_ANALYZER = true; -} - -if ( hasArgInCLI( '--webpack--devtool' ) ) { - process.env.WP_DEVTOOL = getArgFromCLI( '--webpack--devtool' ); -} - -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 webpackArgs = getWebpackArgs(); if ( hasArgInCLI( '--hot' ) ) { webpackArgs.unshift( 'serve' ); diff --git a/packages/scripts/utils/config.js b/packages/scripts/utils/config.js index 3d99f3784859df..be6f1831378911 100644 --- a/packages/scripts/utils/config.js +++ b/packages/scripts/utils/config.js @@ -9,6 +9,7 @@ const { sync: glob } = require( 'fast-glob' ); * Internal dependencies */ const { + getArgFromCLI, getArgsFromCLI, getFileArgsFromCLI, hasArgInCLI, @@ -114,9 +115,37 @@ const getWebpackArgs = () => { // Gets all args from CLI without those prefixed with `--webpack`. let webpackArgs = getArgsFromCLI( [ '--experimental-modules', + '--source-path', '--webpack', ] ); + if ( hasArgInCLI( '--experimental-modules' ) ) { + process.env.WP_EXPERIMENTAL_MODULES = true; + } + + if ( hasArgInCLI( '--source-path' ) ) { + process.env.WP_SOURCE_PATH = getArgFromCLI( '--source-path' ); + } else if ( hasArgInCLI( '--webpack-src-dir' ) ) { + // Backwards compatibility. + process.env.WP_SOURCE_PATH = getArgFromCLI( '--webpack-src-dir' ); + } + + if ( hasArgInCLI( '--webpack-bundle-analyzer' ) ) { + process.env.WP_BUNDLE_ANALYZER = true; + } + + if ( hasArgInCLI( '--webpack-copy-php' ) ) { + process.env.WP_COPY_PHP_FILES_TO_DIST = true; + } + + if ( hasArgInCLI( '--webpack--devtool' ) ) { + process.env.WP_DEVTOOL = getArgFromCLI( '--webpack--devtool' ); + } + + if ( hasArgInCLI( '--webpack-no-externals' ) ) { + process.env.WP_NO_EXTERNALS = true; + } + const hasWebpackOutputOption = hasArgInCLI( '-o' ) || hasArgInCLI( '--output' ); if ( @@ -136,10 +165,6 @@ const getWebpackArgs = () => { const pathToEntry = ( path ) => { const entryName = basename( path, '.js' ); - if ( ! path.startsWith( './' ) ) { - path = './' + path; - } - return [ entryName, path ]; }; @@ -162,7 +187,11 @@ const getWebpackArgs = () => { const [ entryName, path ] = fileArg.includes( '=' ) ? fileArg.split( '=' ) : pathToEntry( fileArg ); - entry[ entryName ] = path; + entry[ entryName ] = fromProjectRoot( + process.env.WP_SOURCE_PATH + ? join( process.env.WP_SOURCE_PATH, path ) + : path + ); } ); process.env.WP_ENTRY = JSON.stringify( entry ); } @@ -176,20 +205,20 @@ const getWebpackArgs = () => { }; /** - * Returns the WordPress source directory. It defaults to 'src' if the - * `process.env.WP_SRC_DIRECTORY` variable is not set. + * Returns the project source path. It defaults to 'src' if the + * `process.env.WP_SOURCE_PATH` variable is not set. * * @return {string} The WordPress source directory. */ -function getWordPressSrcDirectory() { - return process.env.WP_SRC_DIRECTORY || 'src'; +function getProjectSourcePath() { + return process.env.WP_SOURCE_PATH || 'src'; } /** - * 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. + * Detects the list of entry points to use with webpack. There are three alternative ways to do this: + * 1. Use the recommended command format that lists the paths to JavaScript files. + * 2. Scan `block.json` files to detect referenced JavaScript and PHP files automatically. + * 3. Fallback to the `src/index.*` file. * * @see https://webpack.js.org/concepts/entry-points/ * @@ -200,31 +229,32 @@ function getWebpackEntryPoints( buildType ) { * @return {Object} The list of entry points. */ return () => { - // 1. Handles the legacy format for entry points when explicitly provided with the `process.env.WP_ENTRY`. + // 1. Uses the recommended command format that lists entry points as paths to JavaScript files. + // Example: `wp-scripts build one.js two.js`. if ( process.env.WP_ENTRY ) { return buildType === 'script' ? JSON.parse( process.env.WP_ENTRY ) : {}; } - // Continue only if the source directory exists. - if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) { + // Continues only if the source directory exists. Defaults to "src" if not explicitly set in the command. + if ( ! hasProjectFile( getProjectSourcePath() ) ) { warn( - `Source directory "${ getWordPressSrcDirectory() }" was not found. Please confirm there is a "src" directory in the root or the value passed to --webpack-src-dir is correct.` + `Source directory "${ getProjectSourcePath() }" was not found. Please confirm there is a "src" directory in the root or the value passed with "--output-path" is correct.` ); return {}; } // 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. + // It scans all discovered files, looks for JavaScript assets, and converts them to entry points. const blockMetadataFiles = glob( '**/block.json', { absolute: true, - cwd: fromProjectRoot( getWordPressSrcDirectory() ), + cwd: fromProjectRoot( getProjectSourcePath() ), } ); if ( blockMetadataFiles.length > 0 ) { const srcDirectory = fromProjectRoot( - getWordPressSrcDirectory() + sep + getProjectSourcePath() + sep ); const entryPoints = {}; @@ -276,7 +306,7 @@ function getWebpackEntryPoints( buildType ) { ) }" listed in "${ blockMetadataFile.replace( fromProjectRoot( sep ), '' - ) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.` + ) }". File is located outside of the "${ getProjectSourcePath() }" directory.` ); continue; } @@ -290,7 +320,7 @@ function getWebpackEntryPoints( buildType ) { `${ entryName }.?(m)[jt]s?(x)`, { absolute: true, - cwd: fromProjectRoot( getWordPressSrcDirectory() ), + cwd: fromProjectRoot( getProjectSourcePath() ), } ); @@ -302,7 +332,7 @@ function getWebpackEntryPoints( buildType ) { ) }" listed in "${ blockMetadataFile.replace( fromProjectRoot( sep ), '' - ) }". File does not exist in the "${ getWordPressSrcDirectory() }" directory.` + ) }". File does not exist in the "${ getProjectSourcePath() }" directory.` ); continue; } @@ -322,15 +352,15 @@ function getWebpackEntryPoints( buildType ) { } // 3. Checks whether a standard file name can be detected in the defined source directory, - // and converts the discovered file to entry point. + // and converts the discovered file to entry point. const [ entryFile ] = glob( 'index.[jt]s?(x)', { absolute: true, - cwd: fromProjectRoot( getWordPressSrcDirectory() ), + cwd: fromProjectRoot( getProjectSourcePath() ), } ); if ( ! entryFile ) { warn( - `No entry file discovered in the "${ getWordPressSrcDirectory() }" directory.` + `No entry file discovered in the "${ getProjectSourcePath() }" directory.` ); return {}; } @@ -412,10 +442,10 @@ function getPhpFilePaths( context, props ) { module.exports = { getJestOverrideConfigFile, + getPhpFilePaths, + getProjectSourcePath, getWebpackArgs, - getWordPressSrcDirectory, getWebpackEntryPoints, - getPhpFilePaths, hasBabelConfig, hasCssnanoConfig, hasJestConfig, diff --git a/packages/scripts/utils/index.js b/packages/scripts/utils/index.js index cb7e592f83d554..e4937d202d4f49 100644 --- a/packages/scripts/utils/index.js +++ b/packages/scripts/utils/index.js @@ -13,10 +13,10 @@ const { } = require( './cli' ); const { getJestOverrideConfigFile, + getPhpFilePaths, + getProjectSourcePath, getWebpackArgs, - getWordPressSrcDirectory, getWebpackEntryPoints, - getPhpFilePaths, hasBabelConfig, hasCssnanoConfig, hasJestConfig, @@ -41,10 +41,10 @@ module.exports = { getJestOverrideConfigFile, getNodeArgsFromCLI, getPackageProp, + getPhpFilePaths, + getProjectSourcePath, getWebpackArgs, - getWordPressSrcDirectory, getWebpackEntryPoints, - getPhpFilePaths, getBlockJsonModuleFields, getBlockJsonScriptFields, hasArgInCLI,