diff --git a/.changeset/happy-pans-jam.md b/.changeset/happy-pans-jam.md new file mode 100644 index 00000000..97457dce --- /dev/null +++ b/.changeset/happy-pans-jam.md @@ -0,0 +1,5 @@ +--- +"10up-toolkit": minor +--- + +Feature: sourcemap option for production builds diff --git a/packages/toolkit/README.md b/packages/toolkit/README.md index 8a3fec17..bfa731c2 100644 --- a/packages/toolkit/README.md +++ b/packages/toolkit/README.md @@ -335,7 +335,7 @@ module.exports = (api) => { }; ``` -- If your're getting SSL errors for the Websocket connection, you may need to explicitly tell webpack what certificate files to use. See the above section "HTTPS and Certificates" +- If you're getting SSL errors for the Websocket connection, you may need to explicitly tell webpack what certificate files to use. See the above section "HTTPS and Certificates" ## Linting @@ -692,9 +692,39 @@ See [SVGO Configuration](https://github.com/svg/svgo#configuration) for more inf 10up-toolkit supports several CLI options that can be used to override settings. +### Production Sourcemaps +> This option was added in 10up-toolkit v6. + +All development builds ship source maps by default, if you wish to ship source maps to production builds you can use the `--sourcemap` cli flag to force the generation of source maps even in production builds. +Alternatively, you can set this up in `package.json`. + +```json +{ + "name": "tenup-theme", + "version": "1.0.0", + "scripts": { + "start": "10up-toolkit build --watch", + "build": "10up-toolkit build", + "format-js": "10up-toolkit format-js", + "lint-js": "10up-toolkit lint-js", + "lint-style": "10up-toolkit lint-style", + "test": "10up-toolkit test-unit-jest" + }, + "devDependencies": { + "10up-toolkit": "^6.0.0" + }, + "10up-toolkit": { + "sourcemap": true, + "entry": { + "admin": "./assets/js/admin/admin.js" + } + } +} +``` + ### Bundle Analyzer -10up-toolkit ships with `webpack-bundle-analyzer` out of the box, and you can enable it by simple passing the `--analyze` option. +10up-toolkit ships with `webpack-bundle-analyzer` out of the box, and you can enable it by simply passing the `--analyze` option. `10up-toolkit build --analyze` diff --git a/packages/toolkit/__tests__/build-project/test.js b/packages/toolkit/__tests__/build-project/test.js index e5493ee8..080d077c 100644 --- a/packages/toolkit/__tests__/build-project/test.js +++ b/packages/toolkit/__tests__/build-project/test.js @@ -60,4 +60,24 @@ describe('build a project (without useBlockAssets)', () => { fs.existsSync(path.join(__dirname, 'dist', 'blocks', 'example-block', 'editor.css')), ).toBeTruthy(); }); + + it('builds and compiles js and css with sourcemaps (--sourcemap)', async () => { + spawn.sync('node', ['../../scripts/build', '--sourcemap'], { + cwd: __dirname, + }); + + expect(fs.existsSync(path.join(__dirname, 'dist', 'js', 'admin.js.map'))).toBeTruthy(); + expect(fs.existsSync(path.join(__dirname, 'dist', 'js', 'frontend.js.map'))).toBeTruthy(); + expect( + fs.existsSync(path.join(__dirname, 'dist', 'css', 'frontend-css.css.map')), + ).toBeTruthy(); + expect( + fs.existsSync(path.join(__dirname, 'dist', 'blocks', 'example-block', 'editor.js.map')), + ).toBeTruthy(); + expect( + fs.existsSync( + path.join(__dirname, 'dist', 'blocks', 'example-block', 'editor.css.map'), + ), + ).toBeTruthy(); + }); }); diff --git a/packages/toolkit/config/__tests__/webpack-basic-config.js b/packages/toolkit/config/__tests__/webpack-basic-config.js index ce3941a2..54236565 100644 --- a/packages/toolkit/config/__tests__/webpack-basic-config.js +++ b/packages/toolkit/config/__tests__/webpack-basic-config.js @@ -189,4 +189,51 @@ describe('webpack.config.js', () => { expect(webpackConfig).toMatchSnapshot(); }); + + it('takes the sourcemap config into account', () => { + const originalNodeEnv = process.env.NODE_ENV; + process.env.NODE_ENV = 'production'; + + getBuildFilesMock.mockReturnValue({}); + getPackageMock.mockReturnValue({ + name: '@10up/component-library', + source: 'src/index.js', + main: 'dist/index.js', + dependencies: { + 'read-pkg': '^5.2.0', + }, + '10up-toolkit': { + sourcemap: true, + }, + }); + + let webpackConfig; + jest.isolateModules(() => { + // eslint-disable-next-line global-require + webpackConfig = require('../webpack.config'); + }); + + expect(webpackConfig.devtool).toBe('source-map'); + + getPackageMock.mockReturnValue({ + name: '@10up/component-library', + source: 'src/index.js', + main: 'dist/index.js', + dependencies: { + 'read-pkg': '^5.2.0', + }, + '10up-toolkit': { + sourcemap: false, + }, + }); + + jest.isolateModules(() => { + // eslint-disable-next-line global-require + webpackConfig = require('../webpack.config'); + }); + + expect(webpackConfig.devtool).toBe(false); + + process.env.NODE_ENV = originalNodeEnv; + }); }); diff --git a/packages/toolkit/config/__tests__/webpack-cli-arguments.js b/packages/toolkit/config/__tests__/webpack-cli-arguments.js index c43d5b51..5c15f715 100644 --- a/packages/toolkit/config/__tests__/webpack-cli-arguments.js +++ b/packages/toolkit/config/__tests__/webpack-cli-arguments.js @@ -168,4 +168,30 @@ describe('webpack.config.js', () => { expect(webpackConfig).toMatchSnapshot(); process.argv.pop(); }); + + it('takes the --sourcemap option into account', () => { + const originalNodeEnv = process.env.NODE_ENV; + process.env.NODE_ENV = 'production'; + + getBuildFilesMock.mockReturnValue({}); + getPackageMock.mockReturnValue({ + name: '@10up/component-library', + source: 'src/index.js', + main: 'dist/index.js', + dependencies: { + 'read-pkg': '^5.2.0', + }, + }); + + process.argv.push('--sourcemap'); + let webpackConfig; + jest.isolateModules(() => { + // eslint-disable-next-line global-require + webpackConfig = require('../webpack.config'); + }); + + expect(webpackConfig.devtool).toBe('source-map'); + process.argv.pop(); + process.env.NODE_ENV = originalNodeEnv; + }); }); diff --git a/packages/toolkit/config/webpack.config.js b/packages/toolkit/config/webpack.config.js index a0d08af5..17251ce8 100644 --- a/packages/toolkit/config/webpack.config.js +++ b/packages/toolkit/config/webpack.config.js @@ -50,7 +50,7 @@ const config = { }; module.exports = { - devtool: isProduction ? false : 'source-map', + devtool: !isProduction || projectConfig.sourcemap ? 'source-map' : false, mode, devServer: getDevServer(config), // using a function here in order to re-evaluate diff --git a/packages/toolkit/utils/config.js b/packages/toolkit/utils/config.js index 5c3f6029..dc25995a 100644 --- a/packages/toolkit/utils/config.js +++ b/packages/toolkit/utils/config.js @@ -108,12 +108,14 @@ const getDefaultConfig = () => { const devServerPort = Number(getArgFromCLI('--port')) || 8000; const analyze = hasArgInCLI('--analyze'); const include = hasArgInCLI('--include') ? getArgFromCLI('--include').split(',') : []; + const sourcemap = hasArgInCLI('--sourcemap'); return { entry: require(fromConfigRoot('buildfiles.config.js')), filenames: require(fromConfigRoot('filenames.config.js')), paths: require(fromConfigRoot('paths.config.js')), wordpress: wpMode !== 'false', + sourcemap, devServer, devServerPort, analyze, @@ -149,6 +151,10 @@ const getTenUpScriptsConfig = () => { } } + if (typeof config.sourcemap !== 'undefined' && typeof config.sourcemap !== 'boolean') { + throw new Error('config.sourcemap should be a boolean'); + } + const configInclude = config.include ?? []; const include = defaultConfig.include.length === 0 ? configInclude : defaultConfig.include; const publicPath = process.env.ASSET_PATH || config.publicPath || defaultConfig.publicPath; @@ -159,6 +165,7 @@ const getTenUpScriptsConfig = () => { ...config, include, publicPath, + sourcemap: Boolean(config.sourcemap), // these properties must be merged filenames: { ...defaultConfig.filenames,