Skip to content

Commit

Permalink
Generate minified .min.js and unminified .js files for GB js entry po…
Browse files Browse the repository at this point in the history
…ints when building (#31732)

* Add .min.js suffix to index script depending on the presence of env var and enqueue .min.js files by default in `client-assets.php`

* Decide what to enqueue depending on the value of the SCRIPT_DEBUG env var

- If set and true, we enqueue the unminified index.js file for the given package;
- If not set or set and false, we enqueue the minified (production) index.min.js file.

* WIP

* Save unminified .js sources before minimizer runs

* No need to pass the mode anymore

* Add packaged version PoC and tests

* Package as internal monorepo npm, remove top-level PoC module

* Add test artifacts

* Use snake case for var, simplify and DRY the asset name

* Hardcode index.min.js for override scripts

* Always refer to index.asset.php as the asset loader scripts

The WebPack build generates them using the `index.asset.php` name format.

* More reliable extension replacement

* Fix lint error

* Fix php lint errors

* Fix another linter error (prefer-alphabetical-devDependencies)

* Update packages/readable-js-assets-webpack-plugin/package.json

Change the plugin version to include a '-prerelease' suffix.

Co-authored-by: Greg Ziółkowski <[email protected]>

* Update packages/readable-js-assets-webpack-plugin/README.md

Fix webpack spelling :)

Co-authored-by: Greg Ziółkowski <[email protected]>

* Add .nmprc and CHANGELOG.md

* Restrict the compressed-size-action to *.min.js assets (and *.css)

Co-authored-by: Jarda Snajdr <[email protected]>
Co-authored-by: Greg Ziółkowski <[email protected]>
  • Loading branch information
3 people committed Jun 10, 2021
1 parent c4a9a01 commit ec50dad
Show file tree
Hide file tree
Showing 20 changed files with 501 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/bundle-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ jobs:
- uses: preactjs/compressed-size-action@7d87f60a6b0c7d193b8183ce859ed00b356ea92f # v2.1.0
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
pattern: '{build/**/*.js,build/**/*.css}'
pattern: '{build/**/*.min.js,build/**/*.css}'
6 changes: 6 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1727,6 +1727,12 @@
"markdown_source": "../packages/react-native-editor/README.md",
"parent": "packages"
},
{
"title": "@wordpress/readable-js-assets-webpack-plugin",
"slug": "packages-readable-js-assets-webpack-plugin",
"markdown_source": "../packages/readable-js-assets-webpack-plugin/README.md",
"parent": "packages"
},
{
"title": "@wordpress/redux-routine",
"slug": "packages-redux-routine",
Expand Down
11 changes: 6 additions & 5 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function gutenberg_override_translation_file( $file, $handle ) {
}

// Ignore scripts that are not found in the expected `build/` location.
$script_path = gutenberg_dir_path() . 'build/' . substr( $handle, 3 ) . '/index.js';
$script_path = gutenberg_dir_path() . 'build/' . substr( $handle, 3 ) . '/index.min.js';
if ( ! file_exists( $script_path ) ) {
return $file;
}
Expand Down Expand Up @@ -236,14 +236,15 @@ function gutenberg_register_packages_scripts( $scripts ) {
// When in production, use the plugin's version as the default asset version;
// else (for development or test) default to use the current time.
$default_version = defined( 'GUTENBERG_VERSION' ) && ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? GUTENBERG_VERSION : time();
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.js' : '.min.js';

foreach ( glob( gutenberg_dir_path() . 'build/*/index.js' ) as $path ) {
foreach ( glob( gutenberg_dir_path() . "build/*/index$suffix" ) as $path ) {
// Prefix `wp-` to package directory to get script handle.
// For example, `…/build/a11y/index.js` becomes `wp-a11y`.
// For example, `…/build/a11y/index.min.js` becomes `wp-a11y`.
$handle = 'wp-' . basename( dirname( $path ) );

// Replace `.js` extension with `.asset.php` to find the generated dependencies file.
$asset_file = substr( $path, 0, -3 ) . '.asset.php';
// Replace suffix and extension with `.asset.php` to find the generated dependencies file.
$asset_file = substr( $path, 0, -( strlen( $suffix ) ) ) . '.asset.php';
$asset = file_exists( $asset_file )
? require( $asset_file )
: null;
Expand Down
4 changes: 4 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"@wordpress/postcss-themes": "file:packages/postcss-themes",
"@wordpress/prettier-config": "file:packages/prettier-config",
"@wordpress/project-management-automation": "file:packages/project-management-automation",
"@wordpress/readable-js-assets-webpack-plugin": "file:packages/readable-js-assets-webpack-plugin",
"@wordpress/scripts": "file:packages/scripts",
"@wordpress/stylelint-config": "file:packages/stylelint-config",
"appium": "1.20.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/dependency-extraction-webpack-plugin/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class DependencyExtractionWebpackPlugin {
}

const assetFilename = buildFilename.replace(
/\.js$/i,
/(\.min)?\.js$/i,
'.asset.' + ( outputFormat === 'php' ? 'php' : 'json' )
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,26 @@ Array [
]
`;

exports[`Webpack \`has-extension-suffix\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '99bd32161d8514cc8c0cb8b0543ace3f');"`;

exports[`Webpack \`has-extension-suffix\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Object {
"externalType": "window",
"request": "lodash",
"userRequest": "lodash",
},
Object {
"externalType": "window",
"request": Array [
"wp",
"blob",
],
"userRequest": "@wordpress/blob",
},
]
`;

exports[`Webpack \`no-default\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array(), 'version' => '7cedfbba436728640c2c4961b598ab32');"`;

exports[`Webpack \`no-default\` should produce expected output: External modules should match snapshot 1`] = `Array []`;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* External dependencies
*/
import { isEmpty } from 'lodash';

/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

isEmpty( isBlobURL( '' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Internal dependencies
*/
const DependencyExtractionWebpackPlugin = require( '../../..' );

module.exports = {
output: {
filename: 'index.min.js',
},
plugins: [ new DependencyExtractionWebpackPlugin() ],
};
1 change: 1 addition & 0 deletions packages/readable-js-assets-webpack-plugin/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
5 changes: 5 additions & 0 deletions packages/readable-js-assets-webpack-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. -->

## Unreleased

Initial release.
39 changes: 39 additions & 0 deletions packages/readable-js-assets-webpack-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Readable JS assets WebPack Plugin

Generate a readable non-minified JS file for each `.min.js` asset.

The end result is that for each JS entrypoint, we get a set of readable and non-minimized `.js` file and a minimized `.min.js`. This allows Gutenberg to follow the WordPress convention of adding a `.min.js` suffix to minimized JS files, while still providing a readable and unminized files that play well with the WordPress i18n machinery.

Consult the [webpack website](https://webpack.js.org) for additional information on webpack concepts.

## Installation

Install the module

```bash
npm install @wordpress/readable-js-assets-webpack-plugin --save-dev
```

**Note**: This package requires Node.js 12.0.0 or later. It also requires webpack 4.8.3 and newer. It is not compatible with older versions.

## Usage

### Webpack

Use this plugin as you would other webpack plugins:

```js
// webpack.config.js
const ReadableJsAssetsWebpackPlugin = require( '@wordpress/readable-js-assets-webpack-plugin' );

module.exports = {
// …snip
plugins: [ new ReadableJsAssetsWebpackPlugin() ],
};
```

**Note:**
- Multiple instances of the plugin are not supported and may produced unexpected results;
- It assumes your webpack pipeline is already generating a `.min.js` JS asset file for each JS entry-point.

<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
41 changes: 41 additions & 0 deletions packages/readable-js-assets-webpack-plugin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );

class AddReadableJsAssetsWebpackPlugin {
extractUnminifiedFiles( compilation ) {
const files = compilation.chunks.flatMap( ( chunk ) => chunk.files );
compilation.unminifiedAssets = files.map( ( file ) => {
const asset = compilation.assets[ file ];
const unminifiedFile = file.replace( /\.min\.js$/, '.js' );
return [ unminifiedFile, asset.source() ];
} );
}
async writeUnminifiedFiles( compilation ) {
for ( const [ file, source ] of compilation.unminifiedAssets ) {
await fs.promises.writeFile(
path.join( compilation.options.output.path, file ),
source
);
}
}
apply( compiler ) {
compiler.hooks.compilation.tap(
this.constructor.name,
( compilation ) => {
compilation.hooks.additionalAssets.tap(
this.constructor.name,
() => this.extractUnminifiedFiles( compilation )
);
}
);
compiler.hooks.afterEmit.tapPromise(
this.constructor.name,
( compilation ) => this.writeUnminifiedFiles( compilation )
);
}
}

module.exports = AddReadableJsAssetsWebpackPlugin;
36 changes: 36 additions & 0 deletions packages/readable-js-assets-webpack-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@wordpress/readable-js-assets-webpack-plugin",
"version": "1.0.0-prerelease",
"description": "Generate a readable JS file for each JS asset.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"keywords": [
"wordpress",
"gutenberg",
"webpack",
"readable",
"minimizer"
],
"homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/readable-js-assets-webpack-plugin/README.md",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/gutenberg.git",
"directory": "packages/readable-js-assets-webpack-plugin"
},
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
},
"engines": {
"node": ">=12.0"
},
"files": [
"index.js"
],
"main": "index.js",
"peerDependencies": {
"webpack": "^4.8.3 || ^5.0.0"
},
"publishConfig": {
"access": "public"
}
}
Loading

0 comments on commit ec50dad

Please sign in to comment.