webpack优化
1、就是减少打包体积,避免加载不需要的资源
提高构建速度
- 缩小编译范围,减少不必要的编译工作,即 modules、mainFields、noParse、includes、exclude、alias全部用起来。
- 开启enforeExtension
- dll
- loader缓存(cacheDirectory)
- dll
DLLPlugin插件,对不常更新的库,一次打包,存在指定位置,后续直接应用不用再次打包,提高构建速度
- extension
extension:['.js','.jsx','.ts','.tsx']
在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在
import './test'
webpack先找test.js
再找test.jsx....直到test.tsx也不存在就报错
所以extension越长,尝试次数越多,所以开启强制enforceExtension
- loader缓存(cacheDirectory)
loader转换文件为webpack能识别的js文件很慢,所有可以缓存提高转椅速度
test exclude includes
- 缩小编译范围
const resolve = dir => path.join(__dirname, '..', dir);
// ...
resolve: {
modules: [ // 指定以下目录寻找第三方模块,避免webpack往父级目录递归搜索
resolve('src'),
resolve('node_modules'),
resolve(config.common.layoutPath)
],
mainFields: ['main'], // 只采用main字段作为入口文件描述字段,减少搜索步骤
alias: {
vue$: "vue/dist/vue.common",
"@": resolve("src") // 缓存src目录为@符号,避免重复寻址
}
},
module: {
noParse: /jquery|lodash/, // 忽略未采用模块化的文件,因此jquery或lodash将不会被下面的loaders解析
// noParse: function(content) {
// return /jquery|lodash/.test(content)
// },
rules: [
{
test: /\.js$/,
include: [ // 表示只解析以下目录,减少loader处理范围
resolve("src"),
resolve(config.common.layoutPath)
],
exclude: file => /test/.test(file), // 排除test目录文件
loader: "happypack/loader?id=happy-babel" // 后面会介绍
},
]
}
编译瓶颈,
- bable等loader解析阶段
同 webpack-parallel-uglify-plugin 插件一样,HappyPack 也能实现并发编译,从而可以大幅提升 loader 的解析速度
- js压缩卡很久
js 压缩是发布编译的最后阶段,通常webpack需要卡好一会,
这是因为压缩 JS 需要先将代码解析成 AST 语法树,
然后需要根据复杂的规则去分析和处理 AST
最后将 AST 还原成 JS,这个过程涉及到大量计算,因此比较耗时
解决办法:用webpack-parallel-uglify-plugin 插件,
由于node单线程,但是可以fork子进程
webpack-parallel-uglify-plugin 能够把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程
从而实现并发编译,进而大幅提升js压缩速度,如下是配置。
减少体积
- 开启webpack-bundle-analyzer分析,查看资源图
- antd lodash echarts没有按需加载
- 提取公共模块
- 必要的库CDN引用externals
其他脚手架以及实现了,unglfy压缩代码,减少不必要的代码moment
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
webpack升级到4以后变化
- CommonsChunkPlugin废弃
由 optimization.splitChunks 和 optimization.runtimeChunk 替代,
前者拆分代码,后者提取runtime代码。
原来的CommonsChunkPlugin产出模块时,会包含重复的代码,并且无法优化异步模块,minchunks的配置也较复杂,splitChunks解决了这个问题;
另外,将 optimization.runtimeChunk 设置为true(或{name: “manifest”}),便能将入口模块中的runtime部分提取出来
- NamedModulesPlugin 废弃,由 optimization.namedModules 替代,生产环境默认开启。
NamedModulesPlugin: 返回热加载时直接返回更新文件名
[HMR] Updated modules:
[HMR] - ./example.js
[HMR] - ./hmr.js
[HMR] Update applied.
没使用:
[HMR] Updated modules:
[HMR] - 39
[HMR] - 40
[HMR] Update applied.
- ModuleConcatenationPlugin 废弃,由 optimization.concatenateModules 替代,生产环境默认开启。
- optimize.UglifyJsPlugin 废弃,由 optimization.minimize 替代,生产环境默认开启
- extract-text-webpack-plugin被mini-css-extract-plugin,不支持热更新,所以要引入 css-hot-loader
其他
-
使用alias(减少导入文件失误)将导入路径映射成一个新的导入路径
-
DLLPlugin插件,对不常更新的库,一次打包,存在指定位置,后续直接应用不用再次打包,提高构建速度
-
lodash
import {chain, cloneDeep} from 'lodash'
- antd按需加载, (全部加载1.9M,按需记载项目中只有1M)
npm install babel-plugin-import --save-dev //不安装会报错
package.json
"babel": {
"presets": [
"react-app"
],
// 实现按需加载,1.9M的包,按需加载后只用了1.0M
"plugins": [
[
"import",
{
"libraryName": "antd",
"style": true
}
]
]
}
- Echarts按需加载
var echarts = require('echarts/lib/echarts');
import 'echarts/lib/chart/map';
- Moment.js locale 打包优化 //脚手架以及做好了
- webpack-bundle-analyzer,项目打包分析,查看哪些冗余的加载
// webpack.config.prod.js(npm run build生效)
// config/webpack.config.dev.js(npm start生效)
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
config/webpack.config.dev.js
...
plugins: [
...
new BundleAnalyzerPlugin(),
...
]
...
typescript在t sx中使用
https://blog.youkuaiyun.com/s2096828/article/details/83744677
@types/react上面时候使用
npm i react
App.jsx
import React from 'react'
import ReactDOM from 'react-dom'
可以正常使用
App.tsx
import React from 'react'
import ReactDOM from 'react-dom'
//会报错,如下:
Cannot find module 'react'
Cannot find module 'react-dom'
因为react 以及react-dom不是使用Ts开发的
Ts不知道React React-dom的类型,以及模块到处了什么,所以要引入.d.ts申明文件
- index.d.ts (和.eslintrc.js同级)
declare module '@uiw/react-codemirror'
declare module 'react-json-editor-viewer'
declare module 'yamljs'
declare module '@antv/g6'
declare module 'react-mermaid'
declare module 'mermaid'
declare interface List{}
但是直接npm i @types/react
- App.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { Component } from 'react
// 就不会报错
babel
https://www.cnblogs.com/tugenhua0707/p/9452471.html
typeScript 在react中使用总结
https://blog.youkuaiyun.com/s2096828/article/details/83744677
打包后的.map文件
项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错
webpack优化
http://louiszhai.github.io/2019/01/04/webpack4/
- webpack升级文章
https://juejin.im/entry/5be93a30e51d457f7a4abc3e - webpack升4坑
https://medium.com/@hiiamyes/upgrade-a-react-project-from-webpack-3-to-webpack-4-7b53b715a38
升级webpack4遇到的问题
问题一
Plugin could not be registered at 'html-webpack-plugin-before-html-processing'. Hook was not found
安装最新版本的html-webpack-plugin-before-html-processing即可解决
npm i html-webpack-plugin@next
npm i html-webpack-plugin@4.0.0-alpha.2
npm i html-webpack-plugin@latest
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw)
问题二
Tapable.plugin is deprecated. Use new API on `.hooks`
解决办法:
npm install extract-text-webpack-plugin@next
问题三
this.htmlWebpackPlugin.getHooks is not a function
解决
new InterpolateHtmlPlugin( env.raw)// 换成下面的
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw)
问题四
Cannot read property 'ts' of undefined
@ multi ./config/polyfills.js ./src/index.tsx main[1]
解决
npm i ts-loader@^4.0.0
问题5
Path variable [contenthash:8] not implemented in this context: static/css/[name].[contenthash:8].css
解决
问题5
Chunk.initial was removed. Use canBeInitial/isOnlyInitial()
解决
webpack-manifest-plugin": "^1.3.2",
升级到webpack-manifest-plugin: "^2.0.4"
npm i webpack-manifest-plugin@^2.0.4
npm create-react-app失败
- 报错如下
npm WARN enoent ENOENT: no such file or directory
- 解决办法
1 sudo npm install -g npm // 更新npm
2 sudo npm cache clean -f // 清除npm缓存
3 sudo npm install -g n // 安装n模块
4 n stable
5 sudo npm install -g cnpm --registry=https://registry.npm.taobao.org //安装淘宝镜像
6 sudo cnpm install -g create-react-app