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
enableReact
to enable React support - Target
node
orbrowserslist
(more targets will be added as needed)
- Use
- Adds
babel-loader
with the@babel/preset-env
preset- Adds
@babel/preset-react
if React support is enabled
- Adds
- Adds target-specific presets for
webpack
5'sexternals
andexternalsPresets
settings - Target-specific output directory under
dist/
-
browserslist
builds todist/web/
-
node
builds 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 todist
-
enableReact
(boolean, default:false
): Whether to enable React support. Adds.jsx
to 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 tosrc
under 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"
},
}
-
main
supports older Node as well asjest
-
browser
is present for completeness; I haven't found it strictly necessary -
exports.webpack
is the entry point for Webpack-
webpack
will grab the first item underexports
matching its conditions, includingbrowser
, so I recommend listingexports.webpack
first in theexports
object - this allows (for example)
scratch-gui
to buildscratch-vm
from source rather than using the prebuilt version, resulting in more optimal output and preventing version conflicts due to bundled dependencies
-
-
exports.default
makeseslint
happy -
exports.browser
andexports.node
preventexports
-aware tools from usingexports.default
for 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