From 35de289fb5b4d1a89a876c42b692838340fd6f21 Mon Sep 17 00:00:00 2001 From: Paul Sealock Date: Thu, 15 Oct 2020 09:50:57 +1300 Subject: [PATCH] New Package: DependencyExtractionWebpackPlugin (https://github.com/woocommerce/woocommerce-admin/pull/5198) * create package * dynamically make package list * better readmne * point to woo's not wp's for starter pack --- plugins/woocommerce-admin/.gitignore | 1 + .../woocommerce-admin/bin/packages/build.js | 34 ++++++++ .../bin/starter-pack/_package.json | 3 +- .../bin/starter-pack/_webpack.config.js | 42 +--------- .../.npmrc | 1 + .../CHANGELOG.md | 3 + .../README.md | 25 ++++++ .../package.json | 28 +++++++ .../src/index.js | 84 +++++++++++++++++++ 9 files changed, 180 insertions(+), 41 deletions(-) create mode 100644 plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/.npmrc create mode 100644 plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/CHANGELOG.md create mode 100644 plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/README.md create mode 100644 plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/package.json create mode 100644 plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/src/index.js diff --git a/plugins/woocommerce-admin/.gitignore b/plugins/woocommerce-admin/.gitignore index 48b9a7b6065..664be1fe01c 100755 --- a/plugins/woocommerce-admin/.gitignore +++ b/plugins/woocommerce-admin/.gitignore @@ -10,6 +10,7 @@ languages/* woocommerce-admin.zip includes/feature-config.php storybook-static/ +packages/dependency-extraction-webpack-plugin/assets # Directories/files that may appear in your environment .DS_Store diff --git a/plugins/woocommerce-admin/bin/packages/build.js b/plugins/woocommerce-admin/bin/packages/build.js index d8699c0c26d..93a9d20fdfc 100755 --- a/plugins/woocommerce-admin/bin/packages/build.js +++ b/plugins/woocommerce-admin/bin/packages/build.js @@ -17,12 +17,14 @@ const mkdirp = require( 'mkdirp' ); const sass = require( 'node-sass' ); const postcss = require( 'postcss' ); const deasync = require( 'deasync' ); +const rimraf = require( 'rimraf' ); /** * Internal dependencies */ const getPackages = require( './get-packages' ); const getBabelConfig = require( './get-babel-config' ); +const { exit } = require( 'process' ); /** * Module Constants @@ -223,12 +225,44 @@ function buildPackage( packagePath ) { process.stdout.write( `${ DONE }\n` ); } +/** + * Build array of packages for consumption for Dependency Extraction + */ +function buildDependencyExtractionAssets() { + const packages = getPackages(); + const packageNames = packages.map( ( packagePath ) => { + return `\n\t'@woocommerce/${ path.basename( packagePath ) }'`; + } ); + const contents = `module.exports = [${ packageNames },\n];\n`; + const DEPENDENCY_EXTRACTION_ASSETS = path.join( + path.resolve( + __dirname, + '../../packages/dependency-extraction-webpack-plugin' + ), + 'assets' + ); + + try { + rimraf( DEPENDENCY_EXTRACTION_ASSETS, () => { + mkdirp.sync( DEPENDENCY_EXTRACTION_ASSETS ); + fs.writeFileSync( + path.join( DEPENDENCY_EXTRACTION_ASSETS, 'packages.js' ), + contents + ); + } ); + } catch ( err ) { + console.log( err ); + exit( 1 ); + } +} + const files = process.argv.slice( 2 ); if ( files.length ) { buildFiles( files ); } else { process.stdout.write( chalk.inverse( '>> Building packages \n' ) ); + buildDependencyExtractionAssets(); getPackages().forEach( buildPackage ); process.stdout.write( '\n' ); } diff --git a/plugins/woocommerce-admin/bin/starter-pack/_package.json b/plugins/woocommerce-admin/bin/starter-pack/_package.json index 4e4027b9585..136e954bb2c 100644 --- a/plugins/woocommerce-admin/bin/starter-pack/_package.json +++ b/plugins/woocommerce-admin/bin/starter-pack/_package.json @@ -21,6 +21,7 @@ }, "devDependencies": { "@wordpress/scripts": "^12.2.1", - "@woocommerce/eslint-plugin": "1.0.0-beta.0" + "@woocommerce/eslint-plugin": "1.0.0-beta.0", + "@woocommerce/dependency-extraction-webpack-plugin": "1.0.0-beta.0" } } diff --git a/plugins/woocommerce-admin/bin/starter-pack/_webpack.config.js b/plugins/woocommerce-admin/bin/starter-pack/_webpack.config.js index 36dd92a9429..7c211bc7ca0 100644 --- a/plugins/woocommerce-admin/bin/starter-pack/_webpack.config.js +++ b/plugins/woocommerce-admin/bin/starter-pack/_webpack.config.js @@ -1,39 +1,5 @@ const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); -const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); - -const requestToExternal = ( request ) => { - const wcDepMap = { - '@woocommerce/components': [ 'window', 'wc', 'components' ], - '@woocommerce/csv-export': [ 'window', 'wc', 'csvExport' ], - '@woocommerce/currency': [ 'window', 'wc', 'currency' ], - '@woocommerce/date': [ 'window', 'wc', 'date' ], - '@woocommerce/navigation': [ 'window', 'wc', 'navigation' ], - '@woocommerce/number': [ 'window', 'wc', 'number' ], - '@woocommerce/settings': [ 'window', 'wc', 'wcSettings' ], - '@woocommerce/tracks': [ 'window', 'wc', 'tracks' ], - }; - - if ( wcDepMap[ request ] ) { - return wcDepMap[ request ]; - } -}; - -const requestToHandle = ( request ) => { - const wcHandleMap = { - '@woocommerce/components': 'wc-components', - '@woocommerce/csv-export': 'wc-csv', - '@woocommerce/currency': 'wc-currency', - '@woocommerce/date': 'wc-date', - '@woocommerce/navigation': 'wc-navigation', - '@woocommerce/number': 'wc-number', - '@woocommerce/settings': 'wc-settings', - '@woocommerce/tracks': 'wc-tracks', - }; - - if ( wcHandleMap[ request ] ) { - return wcHandleMap[ request ]; - } -}; +const WooCommerceDependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' ); module.exports = { ...defaultConfig, @@ -42,10 +8,6 @@ module.exports = { ( plugin ) => plugin.constructor.name !== 'DependencyExtractionWebpackPlugin' ), - new DependencyExtractionWebpackPlugin( { - injectPolyfill: true, - requestToExternal, - requestToHandle, - } ), + new WooCommerceDependencyExtractionWebpackPlugin(), ], }; diff --git a/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/.npmrc b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/.npmrc new file mode 100644 index 00000000000..9cf9495031e --- /dev/null +++ b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/CHANGELOG.md new file mode 100644 index 00000000000..fb65a938145 --- /dev/null +++ b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -0,0 +1,3 @@ +# 1.0.0-beta.0 + +- Released package diff --git a/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/README.md b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/README.md new file mode 100644 index 00000000000..617254eec2b --- /dev/null +++ b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/README.md @@ -0,0 +1,25 @@ +# Dependency Extraction Webpack Plugin + +Extends Wordpress [Dependency Extraction Webpack Plugin](https://github.com/WordPress/gutenberg/tree/master/packages/dependency-extraction-webpack-plugin) to automatically include WooCommerce dependencies in addition to WordPress dependencies. + +## Installation + +Install the module + +``` +npm install @woocommerce/dependency-extraction-webpack-plugin --save-dev +``` + +## Usage + +Use this as you would [Dependency Extraction Webpack Plugin](https://github.com/WordPress/gutenberg/tree/master/packages/dependency-extraction-webpack-plugin). The API is exactly the same, except that WooCommerce packages are also handled automatically. + +```js +// webpack.config.js +const WooCommerceDependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' ); + +module.exports = { + // …snip + plugins: [ new WooCommerceDependencyExtractionWebpackPlugin() ], +}; +``` diff --git a/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/package.json b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/package.json new file mode 100644 index 00000000000..13bd95654bb --- /dev/null +++ b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/package.json @@ -0,0 +1,28 @@ +{ + "name": "@woocommerce/dependency-extraction-webpack-plugin", + "version": "1.0.0-beta.0", + "description": "WooCommerce Dependency Extraction Webpack Plugin", + "author": "Automattic", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "woocommerce" + ], + "homepage": "https://github.com/woocommerce/woocommerce-admin/tree/main/packages/dependency-extraction-webpack-plugin/README.md", + "repository": { + "type": "git", + "url": "https://github.com/woocommerce/woocommerce-admin.git" + }, + "bugs": { + "url": "https://github.com/woocommerce/woocommerce-admin/issues" + }, + "main": "build/index.js", + "module": "build-module/index.js", + "react-native": "src/index", + "dependencies": { + "@wordpress/dependency-extraction-webpack-plugin": "^2.8.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/src/index.js b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/src/index.js new file mode 100644 index 00000000000..a1c77d4dd2f --- /dev/null +++ b/plugins/woocommerce-admin/packages/dependency-extraction-webpack-plugin/src/index.js @@ -0,0 +1,84 @@ +const WPDependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); +const packages = require( '../assets/packages' ); + +const WOOCOMMERCE_NAMESPACE = '@woocommerce/'; + +/** + * Given a string, returns a new string with dash separators converted to + * camelCase equivalent. This is not as aggressive as `_.camelCase` in + * converting to uppercase, where Lodash will also capitalize letters + * following numbers. + * + * @param {string} string Input dash-delimited string. + * + * @return {string} Camel-cased string. + */ +function camelCaseDash( string ) { + return string.replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() ); +} + +const wooRequestToExternal = ( request ) => { + if ( packages.includes( request ) ) { + return [ + 'wc', + camelCaseDash( request.substring( WOOCOMMERCE_NAMESPACE.length ) ), + ]; + } +}; + +const wooRequestToHandle = ( request ) => { + if ( packages.includes( request ) ) { + return 'wc-' + request.substring( WOOCOMMERCE_NAMESPACE.length ); + } +}; + +class DependencyExtractionWebpackPlugin extends WPDependencyExtractionWebpackPlugin { + externalizeWpDeps( _context, request, callback ) { + let externalRequest; + + // Handle via options.requestToExternal first + if ( typeof this.options.requestToExternal === 'function' ) { + externalRequest = this.options.requestToExternal( request ); + } + + // Cascade to default if unhandled and enabled + if ( + typeof externalRequest === 'undefined' && + this.options.useDefaults + ) { + externalRequest = wooRequestToExternal( request ); + } + + if ( externalRequest ) { + this.externalizedDeps.add( request ); + + return callback( null, { this: externalRequest } ); + } + + // Fall back to the WP method + return super.externalizeWpDeps( _context, request, callback ); + } + + mapRequestToDependency( request ) { + // Handle via options.requestToHandle first + if ( typeof this.options.requestToHandle === 'function' ) { + const scriptDependency = this.options.requestToHandle( request ); + if ( scriptDependency ) { + return scriptDependency; + } + } + + // Cascade to default if enabled + if ( this.options.useDefaults ) { + const scriptDependency = wooRequestToHandle( request ); + if ( scriptDependency ) { + return scriptDependency; + } + } + + // Fall back to the WP method + return super.mapRequestToDependency( request ); + } +} + +module.exports = DependencyExtractionWebpackPlugin;