Skip to content

Commit

Permalink
Add packaged version PoC and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fullofcaffeine committed May 21, 2021
1 parent b793205 commit 9333972
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 1 deletion.
6 changes: 5 additions & 1 deletion add-readable-js-assets-webpack-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );

class AddReadableJsAssetsWebpackPlugin {
extractUnminifiedFiles( compilation ) {
Expand All @@ -14,7 +15,10 @@ class AddReadableJsAssetsWebpackPlugin {
}
async writeUnminifiedFiles( compilation ) {
for ( const [ file, source ] of compilation.unminifiedAssets ) {
await fs.promises.writeFile( file, source );
await fs.promises.writeFile(
path.join( compilation.options.output.path, file ),
source
);
}
}
apply( compiler ) {
Expand Down
6 changes: 6 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,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
37 changes: 37 additions & 0 deletions packages/readable-js-assets-webpack-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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.
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",
"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"
}
}
53 changes: 53 additions & 0 deletions packages/readable-js-assets-webpack-plugin/test/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* External dependencies
*/
const fs = require( 'fs' );
const glob = require( 'glob' ).sync;
const mkdirp = require( 'mkdirp' ).sync;
const path = require( 'path' );
const rimraf = require( 'rimraf' ).sync;
const webpack = require( 'webpack' );

const testDirectory = path.join( __dirname, 'fixtures' );

afterAll( () => rimraf( path.join( __dirname, 'build' ) ) );

describe( 'ReadableJsAssetsWebpackPlugin', () => {
const outputDirectory = path.join( __dirname, 'build' );

beforeEach( () => {
rimraf( outputDirectory );
mkdirp( outputDirectory );
} );

// This afterEach is necessary to prevent watched tests from retriggering on every run.
afterEach( () => rimraf( outputDirectory ) );

test( 'should produce the expected output', () =>
new Promise( ( resolve ) => {
const options = Object.assign(
{
context: testDirectory,
},
require( path.join( testDirectory, 'webpack.config.js' ) )
);
options.output.path = outputDirectory;

webpack( options, ( err ) => {
expect( err ).toBeNull();

const assetFiles = glob( `${ outputDirectory }/*.js` );

expect( assetFiles ).toHaveLength( 4 );

// Asset files should match.
assetFiles.forEach( ( assetFile ) => {
expect(
fs.readFileSync( assetFile, 'utf-8' )
).toMatchSnapshot( 'Asset file should match snapshot' );
} );

resolve();
} );
} ) );
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* External dependencies
*/
const TerserPlugin = require( 'terser-webpack-plugin' );
const path = require( 'path' );

/**
* Internal dependencies
*/
const ReadableJsAssetsWebpackPlugin = require( '../..' );

module.exports = {
mode: 'production',
optimization: {
// Only concatenate modules in production, when not analyzing bundles.
chunkIds: 'named',
moduleIds: 'named',
concatenateModules: true,
minimizer: [
new TerserPlugin( {
cache: true,
parallel: true,
sourceMap: true,
terserOptions: {
output: {
comments: /translators:/i,
},
compress: {
passes: 2,
},
mangle: {
reserved: [ '__', '_n', '_nx', '_x' ],
},
},
extractComments: false,
} ),
],
},
entry: {
index: './index.js',
frontend: './frontend.js',
},
output: {
filename: '[name].min.js',
},
plugins: [ new ReadableJsAssetsWebpackPlugin() ],
};

0 comments on commit 9333972

Please sign in to comment.