build: upgrade to webpack 5

This commit is contained in:
Haishan 2020-10-11 19:31:32 +08:00
parent 2ad0217ee4
commit 9b52b33180
10 changed files with 1725 additions and 1165 deletions

View file

@ -5,7 +5,7 @@ const presets = [
modules: false,
// see also zloirock/core-js https://bit.ly/2JLnrgw
useBuiltIns: 'usage',
corejs: 3,
corejs: '3.6',
// new in babel 7.9.0 https://babeljs.io/blog/2020/03/16/7.9.0
bugfixes: true,
},

View file

@ -5,7 +5,7 @@
"scripts": {
"lint": "eslint --fix --cache src",
"start": "NODE_ENV=development node server.js",
"build": "NODE_ENV=production webpack -p --progress",
"build": "NODE_ENV=production webpack --progress",
"pretty": "prettier --single-quote --write 'src/**/*.{js,scss}'"
},
"husky": {
@ -41,7 +41,7 @@
"date-fns": "^2.16.0",
"fontsource-open-sans": "^3.0.9",
"fontsource-roboto-mono": "^3.0.3",
"framer-motion": "^2.8.0",
"framer-motion": "^2.9.0",
"history": "^5.0.0",
"immer": "^7.0.9",
"invariant": "^2.2.4",
@ -76,12 +76,11 @@
"@babel/preset-flow": "^7.7.4",
"@babel/preset-react": "^7.7.4",
"@babel/preset-typescript": "^7.10.1",
"@hsjs/react-refresh-webpack-plugin": "^0.1.3",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.2",
"@types/invariant": "^2.2.33",
"@types/jest": "^26.0.14",
"@types/lodash-es": "^4.17.3",
"@types/react": "^16.9.51",
"@types/react": "^16.9.52",
"@types/react-dom": "^16.9.8",
"@typescript-eslint/eslint-plugin": "^4.4.0",
"@typescript-eslint/parser": "^4.4.0",
@ -91,6 +90,7 @@
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^6.2.1",
"css-loader": "^4.3.0",
"css-minimizer-webpack-plugin": "^1.1.5",
"cssnano": "^4.1.7",
"eslint": "^7.11.0",
"eslint-config-airbnb-base": "^14.1.0",
@ -110,7 +110,7 @@
"html-webpack-plugin": "^4.5.0",
"husky": "^4.3.0",
"lint-staged": "^10.4.0",
"mini-css-extract-plugin": "^0.12.0",
"mini-css-extract-plugin": "^1.0.0",
"postcss": "^8.1.1",
"postcss-custom-media": "^7.0.8",
"postcss-extend-rule": "^3.0.0",
@ -121,13 +121,13 @@
"prettier": "^2.1.2",
"react-refresh": "^0.8.2",
"resize-observer-polyfill": "^1.5.1",
"style-loader": "^1.3.0",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.2.3",
"ts-loader": "^8.0.4",
"typescript": "4.1.0-beta",
"webpack": "^4.44.2",
"webpack": "^5.0.0",
"webpack-bundle-analyzer": "^3.9.0",
"webpack-cli": "^3.3.12",
"webpack-cli": "^4.0.0",
"webpack-dev-middleware": "^3.7.2",
"webpack-hot-middleware": "^2.22.2"
}

View file

@ -1,5 +1,3 @@
'use strict';
const path = require('path');
const config = require('./webpack.config');
const webpack = require('webpack');
@ -12,7 +10,7 @@ const hotMiddleware = require('webpack-hot-middleware');
const { PORT } = process.env;
const port = PORT ? Number(PORT) : 3000;
config.entry.app.unshift('webpack-hot-middleware/client');
config.entry.app.import.unshift('webpack-hot-middleware/client');
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
@ -29,7 +27,7 @@ const stats = {
cached: false,
cachedAssets: false,
chunks: false,
chunkModules: false
chunkModules: false,
};
const options = { publicPath, stats };

View file

@ -1,7 +1,8 @@
import { motion } from 'framer-motion';
import React from 'react';
import ResizeObserver from 'resize-observer-polyfill';
import { framerMotionResouce } from '../misc/motion';
const { memo, useState, useRef, useEffect } = React;
function usePrevious(value) {
@ -50,6 +51,8 @@ const variantsCollpapsibleChildContainer = {
};
const Collapsible = memo(({ children, isOpen }) => {
const module = framerMotionResouce.read();
const motion = module.motion;
const previous = usePrevious(isOpen);
const [refToMeature, { height }] = useMeasure();
return (

View file

@ -1,5 +1,4 @@
import cx from 'clsx';
import { motion } from 'framer-motion';
import PropTypes from 'prop-types';
import React from 'react';
import { Info } from 'react-feather';
@ -13,6 +12,7 @@ import {
} from 'react-icons/fc';
import { Link, useLocation } from 'react-router-dom';
import { framerMotionResouce } from '../misc/motion';
import { getTheme, switchTheme } from '../store/app';
import s from './SideBar.module.css';
import { connect } from './StateProvider';
@ -130,6 +130,8 @@ function SideBar({ dispatch, theme }) {
}
function MoonA() {
const module = framerMotionResouce.read();
const motion = module.motion;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
@ -153,6 +155,9 @@ function MoonA() {
}
function Sun() {
const module = framerMotionResouce.read();
const motion = module.motion;
return (
<svg
xmlns="http://www.w3.org/2000/svg"

View file

@ -1,8 +1,8 @@
import { formatDistance } from 'date-fns';
import { motion } from 'framer-motion';
import * as React from 'react';
import { RotateCw, Zap } from 'react-feather';
import { framerMotionResouce } from '../../misc/motion';
import {
getClashAPIConfig,
getCollapsibleIsOpen,
@ -117,6 +117,8 @@ const arrow = {
hover: { rotate: 360, transition: { duration: 0.3 } },
};
function Refresh() {
const module = framerMotionResouce.read();
const motion = module.motion;
return (
<motion.div
className={s.refresh}

View file

@ -0,0 +1,45 @@
// from https://gist.github.com/ryanflorence/e10cc9dbc0e259759ec942ba82e5b57c
export function createResource(getPromise: (key: string) => Promise<any>) {
let cache = {};
const inflight = {};
const errors = {};
function load(key = 'default') {
inflight[key] = getPromise(key)
.then((val) => {
delete inflight[key];
cache[key] = val;
})
.catch((error) => {
errors[key] = error;
});
return inflight[key];
}
function preload(key = 'default') {
if (cache[key] !== undefined || inflight[key]) return;
load(key);
}
function read(key = 'default') {
if (cache[key] !== undefined) {
return cache[key];
} else if (errors[key]) {
throw errors[key];
} else if (inflight[key]) {
throw inflight[key];
} else {
throw load(key);
}
}
function clear(key: 'default') {
if (key) {
delete cache[key];
} else {
cache = {};
}
}
return { preload, read, clear };
}

5
src/misc/motion.ts Normal file
View file

@ -0,0 +1,5 @@
import { createResource } from './createResource';
export const framerMotionResouce = createResource(
() => import('framer-motion')
);

View file

@ -7,6 +7,7 @@ const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
@ -47,7 +48,6 @@ const postcssPlugins = () =>
require('postcss-nested')(),
require('autoprefixer')(),
require('postcss-extend-rule')(),
isDev ? false : require('cssnano')(),
].filter(Boolean);
const postcssOptions = { plugins: postcssPlugins() };
@ -74,7 +74,7 @@ const plugins = [
new CleanWebpackPlugin(),
// chart.js requires moment
// and we don't need locale stuff in moment
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.IgnorePlugin({ resourceRegExp: /(^\.\/locale$)|(moment$)/ }),
// https://github.com/pmmmwh/react-refresh-webpack-plugin
isDev
? new ReactRefreshWebpackPlugin({
@ -93,8 +93,10 @@ module.exports = {
// https://webpack.js.org/configuration/devtool/
devtool: isDev ? 'eval-source-map' : 'source-map',
entry: {
// app: ['react-hot-loader/patch', './src/app.js']
app: ['./src/app.js'],
app: { import: ['./src/app.js'], dependOn: 'libs' },
libs: { import: ['react-query', 'react-modal'], dependOn: 'vendor' },
vendor: { import: ['react', 'react-dom'], dependOn: 'corejs' },
corejs: { import: 'core-js' },
},
context: __dirname,
output: {
@ -111,6 +113,14 @@ module.exports = {
},
module: {
rules: [
// to work around "Module not found" issue for babel runtime imports
// https://github.com/webpack/webpack/issues/11467
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
{
test: /\.[tj]sx?$/,
exclude: /node_modules/,
@ -149,33 +159,15 @@ module.exports = {
],
},
optimization: {
moduleIds: isDev ? 'named' : 'hashed',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
'core-js': {
test(module, _chunks) {
return (
module.resource &&
module.resource.indexOf('node_modules/core-js/') >= 0
);
},
},
react: {
test(module, _chunks) {
return (
module.resource &&
(module.resource.indexOf('node_modules/@hot-loader/react-dom/') >=
0 ||
module.resource.indexOf('node_modules/react-dom/') >= 0 ||
module.resource.indexOf('node_modules/react/') >= 0)
);
},
},
},
},
minimizer: [new TerserPlugin()],
splitChunks: { chunks: 'all' },
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
},
plugins,
bail: true,
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
};

2746
yarn.lock

File diff suppressed because it is too large Load diff