Shared configuration for Scratch's use of webpack
Add something like this to your webpack.config.*js file:
import ScratchWebpackConfigBuilder from 'scratch-webpack-configuration';
const builder = new ScratchWebpackConfigBuilder(
{
rootPath: __dirname,
enableReact: true
})
.setTarget('browserslist')
.addModuleRule({
test: /\.css$/,
use: [/* CSS loaders */]
})
.addPlugin(new CopyWebpackPlugin({
patterns: [/* CopyWebpackPlugin patterns */]
});
if (process.env.FOO === 'bar') {
builder.addPlugin(new MyCustomPlugin());
}
module.exports = builder.get();Call addModuleRule and addPlugin as few or as many times as needed. If you need multiple configurations, you can
use clone() to share a base configuration and then add or override settings:
const baseConfig = new ScratchWebpackConfigBuilder({rootPath: __dirname, libraryName: 'my-library'})
.addModuleRule({
test: /\.foo$/,
use: [/* FOO loaders */]
});
const config1 = baseConfig.clone()
.setTarget('browserslist')
.merge({/* arbitrary configuration */})
.addPlugin(new MyCustomPlugin('hi'));
const config2 = baseConfig.clone()
.setTarget('node')
.addPlugin(new MyCustomPlugin('hello'));
module.exports = [
config1.get(),
config2.get()
];- Sets up a default configuration that is suitable for most Scratch projects
- Use
enableReactto enable React support - Target
nodeorbrowserslist(more targets will be added as needed)
- Use
- Adds
babel-loaderwith the@babel/preset-envpreset- Adds
@babel/preset-reactif React support is enabled
- Adds
- Adds target-specific presets for
webpack5'sexternalsandexternalsPresetssettings - Target-specific output directory under
dist/browserslistbuilds todist/web/nodebuilds todist/node/
- Supports merging in arbitrary configuration with
merge({...})
This configuration makes webpack 5's Asset Modules available through resource queries parameters:
import myImage from './my-image.png?asset'; // Use `asset` (let webpack decide)
import myImage from './my-image.png?resource'; // Use `asset/resource`, similar to `file-loader`
import myImage from './my-image.png?inline'; // Use `asset/inline`, similar to `url-loader`
import myImage from './my-image.png?source'; // Use `asset/source`, similar to `raw-loader`You can also use file for asset/resource, url for asset/inline, and raw for asset/source, to make it clear
which loader you're replacing.
Creates a new ScratchWebpackConfigBuilder instance.
Required:
rootPath(string, required): The root path of the project. This is used to establish defaults for other paths.
Optional:
distPath(string, default:path.join(rootPath, 'dist')): The path to the output directory. Defaults todistenableReact(boolean, default:false): Whether to enable React support. Adds.jsxto the list of extensions to process, and adjusts Babel settings.libraryName(string, default:undefined): If set, configures a default entry point and output library name. under the root path.srcPath(string, default:path.join(rootPath, 'src')): The path to the source directory. Defaults tosrcunder the root path.
The exports field in package.json
Most project.json files specify a main entry point, and some specify browser as well. Newer versions of Node
support the exports field as well. If both are present, exports will take precedence.
For more information about exports, see: https://webpack.js.org/guides/package-exports/, especially the "Target
environment" section.
Unfortunately, plenty of tools don't support exports yet, and some that do exhibit some surprising quirks.
Here's what I currently recommend for a project with only one entry point:
{
"main": "./dist/node/foo.js",
"browser": "./dist/web/foo.js",
"exports": {
"webpack": "./src/index.js",
"browser": "./dist/web/foo.js",
"node": "./dist/node/foo.js",
"default": "./src/index.js"
},
}mainsupports older Node as well asjestbrowseris present for completeness; I haven't found it strictly necessaryexports.webpackis the entry point for Webpackwebpackwill grab the first item underexportsmatching its conditions, includingbrowser, so I recommend listingexports.webpackfirst in theexportsobject- this allows (for example)
scratch-guito buildscratch-vmfrom source rather than using the prebuilt version, resulting in more optimal output and preventing version conflicts due to bundled dependencies
exports.defaultmakeseslinthappyexports.browserandexports.nodepreventexports-aware tools from usingexports.defaultfor all contexts
Note that using src/index.js for the webpack and default exports means that the NPM package must include src.
While it could be handy to include browserslist configuration in this package, there are tools other than webpack
that should use the same browserslist configuration. For that reason, I recommend configuring browserslist in
your package.json file or in a top-level .browserslistrc file.
The Scratch system requirements determine the browsers we should target. That information can be found here: https://scratch.mit.edu/faq