编译阶段的优化
开发阶段构建更快
- loader的include和exclude属性
{test: /.(j|t)sx?$/,use: [{loader: "thread-loader",},{loader: "babel-loader",options: {presets: [["@babel/preset-env", { modules: false }], //es6->es5"@babel/preset-react", // react->es5"@babel/preset-typescript", //ts->es5],plugins: [//按需加载["import", { libraryName: "antd", style: "css" }],],},},],include: path.resolve("src"),exclude: /node_modules/,},
- resolve
resolve: {modules: [path.resolve('node_modules')], //配置模块的查找范围extensions: [".ts", ".tsx", ".js", ".json", ".jsx"],alias: {"@": resolvePath("./src"),views: resolvePath("@/views"),},// webpack5之后不再有node模块的profill了,不配置也行fallback: {crypto: false, //不包含crypto的profillbuffer: false,//不包含crypto的profillstream: false,//不包含crypto的profill}},
- 编译缓存
cache 会在开发 模式被设置成 type: ‘memory’ 而且在 生产 模式 中被禁用。 cache: true 与 cache: { type: ‘memory’ } 配置作用一致
开发模式下默认开启。
// webpack5新增的新功能,缓存cache: {type: "memory",},
webpack4的话可以使用插件进行缓存
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
{
plugins: [new HardSourceWebpackPlugin()]
}
第二次编译速度快80%,也是进行缓存。
- 开启多进程
thread-loader,会开启多进程来执行babel-loader。
{test: /.(j|t)sx?$/,use: [{loader: "thread-loader",},{loader: "babel-loader",options: {presets: [["@babel/preset-env", { modules: false }], //es6->es5"@babel/preset-react", // react->es5"@babel/preset-typescript", //ts->es5],plugins: [//按需加载["import", { libraryName: "antd", style: "css" }],],},},],include: path.resolve("src"),exclude: /node_modules/,},
路由切换优化
懒加载实现
类似React.lazy的功能。当需要用到的时候才会去加载。原理类似jsonp。
- 实现懒加载:
const LoadHome: any = React.lazy(() => import("./Home"));
const LoadUser: any = React.lazy(() => import("./User"));const App = () => {useSetRem();return (<HashRouter><React.Suspense fallback={<div>loading....</div>}><ul><li><Link to="/">home</Link></li><li>{" "}<Link to="/user">user</Link></li></ul><Routes><Route path="/" element={<LoadHome />}></Route><Route path="/user" element={<LoadUser />}></Route></Routes></React.Suspense></HashRouter>);
};
官方提供了React.lazy方法,
点home的时候再去加载。原理其实很容易。
实现:
const lazy = (loadComponent) => {return class extends React.Component {state = { Component: null };componentDidMount() {loadComponent().then((res) => {this.setState({ Component: res.default });});}render() {const { Component } = this.state as any;return Component && <Component />;}};
};
- 主要就是()=>import(‘xx’)返回的是一个Promise,
- 首先lazy返回一个什么都不渲染的组件,只有等组件开始渲染才会执行生命周期函数。
- 配合Route,当匹配到路径的时候,Route才会去渲染element,
- 所以当匹配到home的时候,页面开始渲染经过lazy包裹的类组件,
- 执行componentDidMount,执行promise,通过then获取到函数组件,然后通过setState改变状态,返回去渲染,从而达到懒加载的目的。
预先请求
浏览器首屏的时候不加载,空闲的时候再加载,如
const LoadHome: any = React.lazy(() =>import("./Home" /*webpackPrefetch: true */ /*webpackChunkName: 'home' */)
);
const LoadUser: any = React.lazy(() =>import("./User" /*webpackPrefetch: true */ /*webpackChunkName: 'user' */)
);const LoadTest: any = React.lazy(() =>import("./Test" /*webpackPrefetch: true */ /*webpackChunkName: 'test' */)
);
使用魔法注释,效果:
会加入这一条link的标签。
当我们切换的时候会发现,已经预先请求好的。
除此之外还有预加载,preloader,与预请求的用法相似,但是他是将该资源的权重升级,首页就需要加载这个资源,就是预加载,用的不好会影响首页加载时间。