diff --git a/package-lock.json b/package-lock.json index 4e337d5bb945a1..25d870a5f8e2c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2830,6 +2830,8 @@ "version": "file:packages/webpack-config", "dev": true, "requires": { + "babel-loader": "^8.0.5", + "source-map-loader": "^0.2.4", "webpack-bundle-analyzer": "^3.0.3", "webpack-livereload-plugin": "^2.2.0" } @@ -3585,15 +3587,80 @@ } }, "babel-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0.tgz", - "integrity": "sha512-lBUGBz411lSfT+8MHPEaqIVQ44odS1D/wxuTMhijqHc9arZR6jhJEaJa0RpZlCSITZoeK6xoDXTaVTrSoFD7IQ==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz", + "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==", "dev": true, "requires": { - "find-cache-dir": "^1.0.0", + "find-cache-dir": "^2.0.0", "loader-utils": "^1.0.2", "mkdirp": "^0.5.1", "util.promisify": "^1.0.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } } }, "babel-messages": { @@ -18524,34 +18591,13 @@ "dev": true }, "source-map-loader": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.3.tgz", - "integrity": "sha512-MYbFX9DYxmTQFfy2v8FC1XZwpwHKYxg3SK8Wb7VPBKuhDjz8gi9re2819MsG4p49HDyiOSUKlmZ+nQBArW5CGw==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", "dev": true, "requires": { "async": "^2.5.0", - "loader-utils": "~0.2.2", - "source-map": "~0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "loader-utils": "^1.1.0" } }, "source-map-resolve": { diff --git a/package.json b/package.json index a50e84b098f0bf..371a491e2c486a 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "@wordpress/postcss-themes": "file:packages/postcss-themes", "@wordpress/scripts": "file:packages/scripts", "@wordpress/webpack-config": "file:packages/webpack-config", - "babel-loader": "8.0.0", "benchmark": "2.1.4", "browserslist": "4.4.1", "chalk": "2.4.1", @@ -111,7 +110,6 @@ "shallow-equals": "1.0.0", "shallowequal": "1.1.0", "sprintf-js": "1.1.1", - "source-map-loader": "0.2.3", "stylelint-config-wordpress": "13.1.0", "uuid": "3.3.2", "webpack-rtl-plugin": "github:yoavf/webpack-rtl-plugin#develop" diff --git a/packages/webpack-config/README.md b/packages/webpack-config/README.md index 5602de2c9ed815..02f0e12ba3529b 100644 --- a/packages/webpack-config/README.md +++ b/packages/webpack-config/README.md @@ -10,4 +10,16 @@ Install the module npm install @wordpress/webpack-config --save-dev ``` +## Usage + +This is how to extend the default WordPress config for Webpack. You have to create your own `webpack.config.js` file in the root of your project, import the config and extend it with your custom settings as follows: + +```js +const { config } = require( '@wordpress/webpack-config' ); + +module.exports = Object.assign( {}, config, { + // apply your changes here +} ); +``` +

Code is Poetry.

diff --git a/packages/webpack-config/config.js b/packages/webpack-config/config.js new file mode 100644 index 00000000000000..b7bd3c9b1c135a --- /dev/null +++ b/packages/webpack-config/config.js @@ -0,0 +1,103 @@ +/** + * External dependencies + */ +const { BundleAnalyzerPlugin } = require( 'webpack-bundle-analyzer' ); +const LiveReloadPlugin = require( 'webpack-livereload-plugin' ); + +/** + * Internal dependencies + */ +const { camelCaseDash } = require( './utils' ); + +/** + * Converts @wordpress require into window reference. + * + * Note this isn't the same as camel case because of the + * way that numbers don't trigger the capitalized next letter. + * + * @example + * wordpressRequire( '@wordpress/api-fetch' ) = 'wp.apiFetch' + * wordpressRequire( '@wordpress/i18n' ) = 'wp.i18n' + * + * @param {string} request import name + * @return {string} global variable reference for import + */ +const wordpressRequire = ( request ) => { + // @wordpress/components -> [ @wordpress, components ] + const [ , name ] = request.split( '/' ); + + // components -> wp.components + return `wp.${ camelCaseDash( name ) }`; +}; + +const wordpressExternals = ( context, request, callback ) => + /^@wordpress\//.test( request ) ? + callback( null, `root ${ wordpressRequire( request ) }` ) : + callback(); + +const externals = [ + { + react: 'React', + 'react-dom': 'ReactDOM', + tinymce: 'tinymce', + moment: 'moment', + jquery: 'jQuery', + lodash: 'lodash', + 'lodash-es': 'lodash', + }, + wordpressExternals, +]; + +const isProduction = process.env.NODE_ENV === 'production'; +const mode = isProduction ? 'production' : 'development'; + +const config = { + mode, + externals, + resolve: { + modules: [ + process.cwd(), + 'node_modules', + ], + alias: { + 'lodash-es': 'lodash', + }, + }, + module: { + rules: [ + { + test: /\.js$/, + use: [ 'source-map-loader' ], + enforce: 'pre', + }, + { + test: /\.js$/, + exclude: [ + /block-serialization-spec-parser/, + /is-shallow-equal/, + /node_modules/, + ], + use: 'babel-loader', + }, + ], + }, + plugins: [ + // GUTENBERG_BUNDLE_ANALYZER global variable enables utility that represents bundle content + // as convenient interactive zoomable treemap. + process.env.GUTENBERG_BUNDLE_ANALYZER && new BundleAnalyzerPlugin(), + // GUTENBERG_LIVE_RELOAD_PORT global variable changes port on which live reload works + // when running watch mode. + ! isProduction && new LiveReloadPlugin( { port: process.env.GUTENBERG_LIVE_RELOAD_PORT || 35729 } ), + ].filter( Boolean ), + stats: { + children: false, + }, +}; + +if ( ! isProduction ) { + // GUTENBERG_DEVTOOL global variable controls how source maps are generated. + // See: https://webpack.js.org/configuration/devtool/#devtool. + config.devtool = process.env.GUTENBERG_DEVTOOL || 'source-map'; +} + +module.exports = config; diff --git a/packages/webpack-config/index.js b/packages/webpack-config/index.js index 4ab9659ced1082..eb022a4e505eb2 100644 --- a/packages/webpack-config/index.js +++ b/packages/webpack-config/index.js @@ -1,104 +1,10 @@ /** - * External dependencies + * Internal dependencies */ -const { BundleAnalyzerPlugin } = require( 'webpack-bundle-analyzer' ); -const LiveReloadPlugin = require( 'webpack-livereload-plugin' ); +const { camelCaseDash } = require( './utils' ); +const config = require( './config' ); -/** - * Converts @wordpress require into window reference - * - * Note this isn't the same as camel case because of the - * way that numbers don't trigger the capitalized next letter - * - * @example - * wordpressRequire( '@wordpress/api-fetch' ) = 'wp.apiFetch' - * wordpressRequire( '@wordpress/i18n' ) = 'wp.i18n' - * - * @param {string} request import name - * @return {string} global variable reference for import - */ -const wordpressRequire = ( request ) => { - // @wordpress/components -> [ @wordpress, components ] - const [ , name ] = request.split( '/' ); - - // components -> wp.components - return `wp.${ name.replace( /-([a-z])/g, ( match, letter ) => letter.toUpperCase() ) }`; -}; - -const wordpressExternals = ( context, request, callback ) => - /^@wordpress\//.test( request ) ? - callback( null, `root ${ wordpressRequire( request ) }` ) : - callback(); - -const externals = [ - { - react: 'React', - 'react-dom': 'ReactDOM', - tinymce: 'tinymce', - moment: 'moment', - jquery: 'jQuery', - lodash: 'lodash', - 'lodash-es': 'lodash', - }, - wordpressExternals, -]; - -const isProduction = process.env.NODE_ENV === 'production'; -const mode = isProduction ? 'production' : 'development'; - -const config = { - mode, - output: { - filename: './build/[basename]/index.js', - path: process.cwd(), - library: [ 'wp', '[name]' ], - libraryTarget: 'this', - }, - externals, - resolve: { - modules: [ - process.cwd(), - 'node_modules', - ], - alias: { - 'lodash-es': 'lodash', - }, - }, - module: { - rules: [ - { - test: /\.js$/, - use: [ 'source-map-loader' ], - enforce: 'pre', - }, - { - test: /\.js$/, - exclude: [ - /block-serialization-spec-parser/, - /is-shallow-equal/, - /node_modules/, - ], - use: 'babel-loader', - }, - ], - }, - plugins: [ - // GUTENBERG_BUNDLE_ANALYZER global variable enables utility that represents bundle content - // as convenient interactive zoomable treemap. - process.env.GUTENBERG_BUNDLE_ANALYZER && new BundleAnalyzerPlugin(), - // GUTENBERG_LIVE_RELOAD_PORT global variable changes port on which live reload works - // when running watch mode. - ! isProduction && new LiveReloadPlugin( { port: process.env.GUTENBERG_LIVE_RELOAD_PORT || 35729 } ), - ].filter( Boolean ), - stats: { - children: false, - }, +module.exports = { + camelCaseDash, + config, }; - -if ( ! isProduction ) { - // GUTENBERG_DEVTOOL global variable controls how source maps are generated. - // See: https://webpack.js.org/configuration/devtool/#devtool. - config.devtool = process.env.GUTENBERG_DEVTOOL || 'source-map'; -} - -module.exports = config; diff --git a/packages/webpack-config/package.json b/packages/webpack-config/package.json index d87db2dade203f..c5ac5e8c452bcd 100644 --- a/packages/webpack-config/package.json +++ b/packages/webpack-config/package.json @@ -23,6 +23,8 @@ }, "main": "index.js", "dependencies": { + "babel-loader": "^8.0.5", + "source-map-loader": "^0.2.4", "webpack-bundle-analyzer": "^3.0.3", "webpack-livereload-plugin": "^2.2.0" }, diff --git a/packages/webpack-config/utils.js b/packages/webpack-config/utils.js new file mode 100644 index 00000000000000..ea6ea3889c1ad8 --- /dev/null +++ b/packages/webpack-config/utils.js @@ -0,0 +1,20 @@ +/** + * 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, + ( match, letter ) => letter.toUpperCase() + ); +} + +module.exports = { + camelCaseDash, +}; diff --git a/webpack.config.js b/webpack.config.js index a57a176d0fc81f..a1c5c5f7726898 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,7 +13,7 @@ const { basename } = require( 'path' ); */ const CustomTemplatedPathPlugin = require( '@wordpress/custom-templated-path-webpack-plugin' ); const LibraryExportDefaultPlugin = require( '@wordpress/library-export-default-webpack-plugin' ); -const webpackConfig = require( '@wordpress/webpack-config' ); +const { camelCaseDash, config } = require( '@wordpress/webpack-config' ); /** * Internal dependencies @@ -22,38 +22,28 @@ const { dependencies } = require( './package' ); const WORDPRESS_NAMESPACE = '@wordpress/'; -/** - * 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, - ( match, letter ) => letter.toUpperCase() - ); -} - const gutenbergPackages = Object.keys( dependencies ) .filter( ( packageName ) => packageName.startsWith( WORDPRESS_NAMESPACE ) ) .map( ( packageName ) => packageName.replace( WORDPRESS_NAMESPACE, '' ) ); -webpackConfig.entry = gutenbergPackages.reduce( ( memo, packageName ) => { +config.entry = gutenbergPackages.reduce( ( memo, packageName ) => { const name = camelCaseDash( packageName ); memo[ name ] = `./packages/${ packageName }`; return memo; }, {} ); -webpackConfig.plugins.push( +config.output = { + filename: './build/[basename]/index.js', + path: __dirname, + library: [ 'wp', '[name]' ], + libraryTarget: 'this', +}; + +config.plugins.push( // Create RTL files with a -rtl suffix new WebpackRTLPlugin( { suffix: '-rtl', - minify: process.env.NODE_ENV === 'production' ? { safe: true } : false, + minify: config.mode === 'production' ? { safe: true } : false, } ), new CustomTemplatedPathPlugin( { basename( path, data ) { @@ -90,7 +80,7 @@ webpackConfig.plugins.push( to: `./build/${ packageName }/`, flatten: true, transform: ( content ) => { - if ( webpackConfig.mode === 'production' ) { + if ( config.mode === 'production' ) { return postcss( [ require( 'cssnano' )( { preset: [ 'default', { @@ -109,4 +99,4 @@ webpackConfig.plugins.push( ) ); -module.exports = webpackConfig; +module.exports = config;