Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: webpack v5 #1645

Merged
merged 4 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/sweet-snakes-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'preact-cli': major
---

- Upgrades to Webpack v5
- Any custom configuration you do in your `preact.config.js` may need to be altered to account for this. Plugins may need replacements or different option formats.

- `--esm` flag has been removed
- Dual output is now enabled by default in production builds.

- `.babelrc` no longer overwrites matching keys
- Instead, the config will be merged in to the default. The default still takes precedence when there are conflicts, so you will still need to use your `preact.config.js` if you want to edit or remove default plugins or presets.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/node_modules
**/tests/output
**/tests/subjects/*/preact.config.js
**/*.d.ts
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,14 @@ Note: If you don't specify enough data to the `npx preact-cli create` command, i

Create a production build

You can disable `default: true` flags by prefixing them with `--no-<option>`; for example, `--no-sw`, `--no-esm`, and `--no-inline-css`.
You can disable `default: true` flags by prefixing them with `--no-<option>`; for example, `--no-sw`, `--no-prerender`, and `--no-inline-css`.

```
$ preact build

--src Specify source directory (default src)
--dest Specify output directory (default build)
--cwd A directory to use instead of $PWD (default .)
--esm Builds ES-2015 bundles for your code (default true)
--sw Generate and attach a Service Worker (default true)
--babelConfig Path to custom Babel config (default .babelrc)
--json Generate build stats for bundle analysis
Expand All @@ -139,7 +138,6 @@ $ preact watch

--src Specify source directory (default src)
--cwd A directory to use instead of $PWD (default .)
--esm Builds ES-2015 bundles for your code (default false)
--clear Clear the console (default true)
--sw Generate and attach a Service Worker (default false)
--babelConfig Path to custom Babel config (default .babelrc)
Expand Down Expand Up @@ -192,25 +190,25 @@ To make customizing your configuration easier, preact-cli supports plugins. Visi

#### Browserslist

You may customize your list of supported browser versions by declaring a [`"browserslist"`] key within your `package.json`. Changing these values will modify your JavaScript (via [`@babel/preset-env`]) and your CSS (via [`autoprefixer`](https://github.com/postcss/autoprefixer)) output.
You may customize your list of supported browser versions by declaring a [`"browserslist"`] key within your `package.json`. Changing these values will modify your legacy JavaScript (via [`@babel/preset-env`]) and your CSS (via [`autoprefixer`](https://github.com/postcss/autoprefixer)) output.

By default, `preact-cli` emulates the following config:

> `package.json`

```json
{
"browserslist": ["> 0.25%", "IE >= 9"]
"browserslist": ["> 0.5%", "last 2 versions", "Firefox ESR", "not dead"]
}
```

#### Babel

To customize Babel, you have two options:

1. You may create a [`.babelrc`] file in your project's root directory. Any settings you define here will overwrite matching config-keys within [Preact CLI preset]. For example, if you pass a `"plugins"` object, it will replace & reset all Babel plugins that Preact CLI defaults to.
1. You may create a [`.babelrc`] file in your project's root directory, or use the `--babelConfig` path to point at any valid [Babel config file]. Any settings you define here will be merged into the [Preact CLI preset]. For example, if you pass a `"plugins"` object containing different plugins from those already in use, they will simply be added on top of the existing config. If there are conflicts, you'll want to look into option 2, as the default will take precedence.

2. If you'd like to modify or add to the existing Babel config, you must use a `preact.config.js` file. Visit the [Webpack](#webpack) section for more info, or check out the [Customize Babel] example!
2. If you'd like to modify the existing Babel config you must use a `preact.config.js` file. Visit the [Webpack](#webpack) section for more info, or check out the [Customize Babel] example!

#### Webpack

Expand Down Expand Up @@ -400,9 +398,9 @@ Automatic code splitting is applied to all JavaScript and TypeScript files in th
[preact]: https://github.com/preactjs/preact
[webpackconfighelpers]: docs/webpack-helpers.md
[`.babelrc`]: https://babeljs.io/docs/usage/babelrc
[babel config file]: https://babeljs.io/docs/en/config-files
[simple]: https://github.com/preactjs-templates/simple
[`"browserslist"`]: https://github.com/ai/browserslist
[```.babelrc```]: https://babeljs.io/docs/usage/babelrc
[default]: https://github.com/preactjs-templates/default
[workbox]: https://developers.google.com/web/tools/workbox
[preact-router]: https://github.com/preactjs/preact-router
Expand Down
52 changes: 0 additions & 52 deletions packages/cli/babel/index.js

This file was deleted.

5 changes: 0 additions & 5 deletions packages/cli/lib/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ const options = [
description: 'A directory to use instead of $PWD',
default: '.',
},
{
name: '--esm',
description: 'Builds ES-2015 bundles for your code',
default: true,
},
{
name: '--sw',
description: 'Generate and attach a Service Worker',
Expand Down
5 changes: 0 additions & 5 deletions packages/cli/lib/commands/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ const options = [
description: 'A directory to use instead of $PWD',
default: '.',
},
{
name: '--esm',
description: 'Builds ES-2015 bundles for your code',
default: false,
},
{
name: '--clear',
description: 'Clear the console',
Expand Down
25 changes: 15 additions & 10 deletions packages/cli/lib/lib/babel-config.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
module.exports = function (env, options = {}) {
const { production: isProd, refresh } = env || {};
const { tryResolveConfig } = require('../util');

module.exports = function (env) {
const { babelConfig, cwd, isProd, refresh } = env;

const resolvedConfig =
babelConfig &&
tryResolveConfig(cwd, babelConfig, babelConfig === '.babelrc');

return {
babelrc: false,
configFile: resolvedConfig,
presets: [
[
!isProd && [
require.resolve('@babel/preset-env'),
{
loose: true,
modules: false,
bugfixes: true,
modules: options.modules || false,
targets: {
browsers: options.browsers,
esmodules: true,
},
exclude: ['transform-regenerator'],
},
],
],
].filter(Boolean),
Comment on lines 13 to +26
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matches what optimize-plugin will output in prod. Now only used in dev.

plugins: [
require.resolve('@babel/plugin-syntax-dynamic-import'),
require.resolve('@babel/plugin-transform-object-assign'),
[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-object-rest-spread'),
isProd &&
require.resolve('babel-plugin-transform-react-remove-prop-types'),
require.resolve('babel-plugin-macros'),
Expand Down
6 changes: 2 additions & 4 deletions packages/cli/lib/lib/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ if (process.env.NODE_ENV === 'development') {
);
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
navigator.serviceWorker.register(
normalizeURL(__webpack_public_path__) +
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
normalizeURL(__webpack_public_path__) + 'sw.js'
);
}
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
navigator.serviceWorker.register(
normalizeURL(__webpack_public_path__) +
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
normalizeURL(__webpack_public_path__) + 'sw.js'
);
}

Expand Down
4 changes: 1 addition & 3 deletions packages/cli/lib/lib/webpack/proxy-loader.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
var utils = require('loader-utils');

function proxyLoader(source, map) {
var options = utils.getOptions(this);
var options = this.getOptions();

// First run proxy-loader run
if (!this.query.__proxy_loader__) {
Expand Down
44 changes: 18 additions & 26 deletions packages/cli/lib/lib/webpack/push-manifest.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
const webpack = require('webpack');
const { Compilation, sources } = require('webpack');
const createLoadManifest = require('./create-load-manifest');

module.exports = class PushManifestPlugin {
apply(compiler) {
compiler.hooks.emit.tap(
{
name: 'PushManifestPlugin',
stage: webpack.Compiler.PROCESS_ASSETS_STAGE_REPORT,
},
compilation => {
const manifest = createLoadManifest(
compilation.assets,
compilation.namedChunkGroups
);
compiler.hooks.thisCompilation.tap('PushManifestPlugin', compilation => {
compilation.hooks.processAssets.tap(
{
name: 'PushManifestPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_REPORT,
},
() => {
const manifest = JSON.stringify(
createLoadManifest(compilation.assets, compilation.namedChunkGroups)
);

let output = JSON.stringify(manifest);
compilation.assets['push-manifest.json'] = {
source() {
return output;
},
size() {
return output.length;
},
};

return compilation;

// callback();
}
);
compilation.emitAsset(
'push-manifest.json',
new sources.RawSource(manifest)
);
}
);
});
}
};
36 changes: 22 additions & 14 deletions packages/cli/lib/lib/webpack/render-html-plugin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { resolve, join } = require('path');
const os = require('os');
const { existsSync, readFileSync, writeFileSync, mkdirSync } = require('fs');
const { Compilation, sources } = require('webpack');
const {
HtmlWebpackSkipAssetsPlugin,
} = require('html-webpack-skip-assets-plugin');
Expand Down Expand Up @@ -110,7 +111,6 @@ module.exports = async function renderHTMLPlugin(config) {
};
},
inject: true,
scriptLoading: 'defer',
rschristian marked this conversation as resolved.
Show resolved Hide resolved
favicon: existsSync(resolve(src, 'assets/favicon.ico'))
? 'assets/favicon.ico'
: '',
Expand Down Expand Up @@ -183,20 +183,28 @@ class PrerenderDataExtractPlugin {
this.data_ = JSON.stringify(page || {});
}
apply(compiler) {
compiler.hooks.emit.tap('PrerenderDataExtractPlugin', compilation => {
if (this.location_ === `${PREACT_FALLBACK_URL}/`) {
// We dont build prerender data for `200.html`. It can re-use the one for homepage.
return;
}
let path = this.location_ + 'preact_prerender_data.json';
if (path.startsWith('/')) {
path = path.substr(1);
compiler.hooks.thisCompilation.tap(
'PrerenderDataExtractPlugin',
compilation => {
compilation.hooks.processAssets.tap(
{
name: 'PrerenderDataExtractPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
},
() => {
if (this.location_ === `${PREACT_FALLBACK_URL}/`) {
// We dont build prerender data for `200.html`. It can re-use the one for homepage.
return;
}
let path = this.location_ + 'preact_prerender_data.json';
if (path.startsWith('/')) {
path = path.substr(1);
}
compilation.emitAsset(path, new sources.RawSource(this.data_));
}
);
}
compilation.assets[path] = {
source: () => this.data_,
size: () => this.data_.length,
};
});
);
}
}

Expand Down
17 changes: 2 additions & 15 deletions packages/cli/lib/lib/webpack/run-webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,26 +96,13 @@ function showStats(stats, isProd) {
if (stats.hasErrors()) {
allFields(stats, 'errors')
.map(stripLoaderPrefix)
.forEach(msg => error(msg, isProd ? 1 : 0));
.forEach(({ message }) => error(message, isProd ? 1 : 0));
}

if (stats.hasWarnings()) {
allFields(stats, 'warnings')
.map(stripLoaderPrefix)
.forEach(msg => {
if (
msg.match(
/Conflict: Multiple assets emit different content to the same filename .*\.(css|map)/
)
) {
/**
* This particular warning is expected due to `babel-esm-plugin`.
* This can be removed when upgrading to webpack5 with https://webpack.js.org/configuration/output/#outputcomparebeforeemit
*/
return;
}
warn(msg);
});
.forEach(({ message }) => warn(message));
}
}

Expand Down
Loading