一、初始化项目
二、配置主要的属性
三、解析过程
四、解析样式文件
1、解析css
module: {
rules: [
{
test: /\.css$/,
// 多个loader是有顺序的,从右往左写,转换的时候是从右往左进行转换的
loader: ['style-loader', 'css-loader'],
// css-loader:用来解析处理css文件中的url路径
// style-loader:可以把css文件变成style标签插入到header中
}
]
}
2、将css文件中bundle.js中分离出来
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:'../'
}
},
"css-loader"
]
}
]
}
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
3、提取css文件到单独文件夹中
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "[id].css"
})
]
// 提取css文件到css文件夹中
4、压缩css样式文件
去除空格、换行
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
plugins: [
new OptimizeCSSAssetsPlugin({})
]
5、解析scss
6、处理css前缀
7、问题总结
- 提取css文件插件更换(’extract-text-webpack-plugin’换成’mini-css-extract-plugin’)
- 压缩写法变化
五、通过插件生成html
```javascript const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’, // 以该html文件为模板,生成文件 filename: ‘index.html’ // 产生后的文件名 }) ]
<a name="lmXzo"></a>
## 六、打包前清除dist文件夹
```javascript
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
new CleanWebpackPlugin()
/*
注意:
const CleanWebpackPlugin = require('clean-webpack-plugin'); 错误写法
new CleanWebpackPlugin(['dist']) 错误写法,新版本不需要指定文件夹名称
会自动根据出入的文件名进行删除,并重新打包创建
*/
七、解析ES6
解析es6需要用到babel。
babel转义靠的就是AST(抽象语法树)
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
https://juejin.im/post/6844904181501952014
1、压缩js
const uglify = require('uglifyjs-webpack-plugin');
new uglify()
八、解析图片和字体
1、通过js new Image()
let src = require('./img/1.png')
let img = new Image()
img.src = src
document.body.appendChild(img)
rules: [{
// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
test: /\.(png|jpg|gif|svg|bmp)/,
use: 'file-loader'
}]
2、在css中当成背景图引入
3、通过img标签引入
需要html-widthimg-loader -D
把图片打包到固定的文件夹目录下
rules: [{
// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
test: /\.(png|jpg|gif|svg|bmp)/,
use: {
loader: 'file-loader',
// 指定拷贝文件的输出目录
options: {
outputPath: 'images/'
}
}
}]
将比较小的图标打包成base64格式,嵌到页面中,这样就能减少一次资源请求了。
rules: [{
// file-loader 是解析图片地址,把图片从资源位置拷贝到目标位置
test: /\.(png|jpg|gif|svg|bmp)/,
use: {
loader: 'url-loader',
// 指定拷贝文件的输出目录
options: {
limit: 9 * 1024, // 小于9kb一下的 就打包成base64
outputPath: 'images/'
}
}
}]
九、配置多页开发
// 先找到每个入口(entry),然后从各个入口分别处罚,找到依赖的模块(module)
// 然后生成一个chunk(代码块)(一个代码块包含很多模块)最后会把chunk写到文件系统中(assets)
entry: {
index: './src/index.js',
base: './src/base.js'
}
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 以该html文件为模板,生成文件
filename: 'index.html', // 产生后的文件名
chunk: ['index']
}),
new HtmlWebpackPlugin({
template: './src/index.html', // 以该html文件为模板,生成文件
filename: 'base.html', // 产生后的文件名
chunk: ['base']
})
]
// 如果页面过多,不可能一直写HtmlWebpackPlugin,可以写for循环
十、公共库的打包
我们模块中使用了公共库,我们不应该把库文件打包到bundle中,这样的话,bundle文件太大。
1、提取公共库文件
cnpm install jquery -S
const $ = require('jquery')
console.log($)
打包之后:
const webpack = require('webpack');
plugin: [
// 全局下都可以使用$代表jquery
new webpack.ProvidePlugin({
$: 'jquery'
})
],
// 提取公共模块,包括第三方库和自定义工具库等
optimization: {
// 找到chunk中共享的模块,取出来生成单独的chunk
splitChunks: {
chunks: "all", // async表示抽取异步模块,all表示对所有模块生效,initial表示对同步模块生效
cacheGroups: {
vendors: { // 抽离第三方插件
test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包
name: "vendors",
priority: -10 // 抽取优先级
},
utilCommon: { // 抽离自定义工具库
name: "common",
minSize: 0, // 将引用模块分离成新代码文件的最小体积
minChunks: 2, // 表示将引用模块如不同文件引用了多少次,才能分离生成新chunk
priority: -20
}
}
},
// 为 webpack 运行时代码创建单独的chunk
runtimeChunk:{
name:'manifest'
}
}
十一、配置别名
reolsve: {
alias: { // 别名
"@": './src'
},
// 命中率高的往前写,命中率低的往后写
extensions: ['', '.js', '.json'] // 配置扩展名(引入模块的时候,可以不加扩展名)
}
十二、优化方案
1、缩小文件搜索范围
// 当你引入一个模块的时候,要进行解析
resolve: {
// 当你需要指定node_modules之外的其他模块目录的话
modules: [path.resolve(__dirname, 'node_modules')],
alias: {
// 当加载react模块的时候,
react: path.resolve('./cjs/react.production.min.js')
}
}
2、noParse 不处理的模块
module.noParse配置可以让webpack忽略对部分没采用慕课话的文件的递归解析处理
module: {
noParse: [/react\.min\.js/]
}
被忽略掉的文件里不应该包含import require define等模块化语句
// 如果打包的文件过大
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader'
}
],
// 只转换或者编译src目录下的文件
include: path.resolve('./src'),
// 排除node_modules
exclude: /node_modules/
}
]
noParse减少打包查询时间,也可以减少打包文件的大小。从而提高构建性能。
3、DLL
.dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据。
- 把基础模块独立处理打包到单独的动态链接库里
- 当需要导入的模块在动态链接库里的时候,模块不能再次被打包,而是去动态链接库里获取dll-plugin
1、定义DLL
- DllPlugin插件:用于打包一个个动态链接库
- DllReferencePlugin:在配置文件中引入DllPlugin插件打包好的动态链接库
4、优化loader的配置
通过include去命中 只有哪些文件去处理,通过exclude去除哪些文件不需要处理,例如node_module5、优化resolve.modules配置
resolve.modules用于配置Webpack去哪些目录下寻找第三方模块。
resolve.modelus的默认值是['node_modules']含义是先去当前目录的./node_modules目录下去找我们想找的模块,如果没找到,就去上一级目录../node_modules中找,再没有就去../../node_modules中找,以此类推
当安装的第三方模块都放在项目根目录的./node_modules目录下时,就没有必要按照默认的方式去一层层的寻找,可以指明存放第三方模块的绝对路径,以减少寻找,配置如下:
module.exports = {
resolve: {
// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
// 其中,__dirname表示当前工作目录,也就是项目根目录
modules: [path.resolve(__dirname,'node_modules')]
}
}
6、优化resolve.alias配置,跳过递归解析操作
7、优化resolve.extensions配置
减少后缀,后缀尽可能的少,这样能提升打包速度,减少打包时间8、ParallelUglifyPlugin
原本会使用Uglifyjs去一个一个压缩再输出
Paralleuglifyplugin会开启多个子线程,将对多个文件的压缩工作分配给多个子进程完成,每个子进程其实还是通过uglify去压缩代码,但是变成了并行执行,所以Paralleuglifyplugin能更快地完成对多个文件的压缩工作9、利用缓存提升二次构建速度
十三、webpack-dev-server
webpack-dev-server打包后的文件,放到了内存中,所以我们在本地文件夹中是看不到的十四、npm 和 npx的区别
npx可以执行命令(.bin目录下的命令,npm无法执行)
npm只能执行脚本命令十五、监控源文件的变化
// 表示监控源文件的变化,当源文件发售改变后,则重新打包
watch: true,
watchOptions: {
exclude/ignored: /node_modules/,
poll: 1000, // 每秒中询问的次数
aggregateTimeout: 500, //
}
十六、文件拷贝
一些不需要打包的依赖文件,需要同时拷贝过去 ```javascript copy-webpack-plugin
const CopyWebpackPlugin = require(‘copy-webpack-plugin’) plugins: [ new CopyWebpackPlugin([{ form: path.join(dirname, ‘public’), to: path.join(dirname, ‘dist’) }]) ]
<a name="aSAzy"></a>
## 十七、自动更新
<a name="H2zNI"></a>
## 十八、区分环境
<a name="3tXUo"></a>
## 十九、配置CDN
<a name="ZvOdB"></a>
## 二十、Tree-shaking
前端中的tree-shaking可以理解为通过工具"摇"我们的JS文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。<br />Tree-shaking的本质是消除无用的js代码。无用代码消除在广泛存在于传统的编程语言编译器中,编译器可以判断出某些代码根本不影响输出,然后消除这些代码,这个称之为DCE(dead code elimination)。<br />Tree-shaking 是 DCE 的一种新的实现,Javascript同传统的编程语言不同的是,javascript绝大多数情况需要通过网络进行加载,然后执行,加载的文件大小越小,整体执行时间更短,所以去除无用代码以减少文件体积,对javascript来说更有意义。
<a name="xRzXh"></a>
## 二十一、开启Scope Hoisting
是webpack3推出的新功能,直译”作用域提升“,他可以让webpack打包出来的代码文件更小,运行更快。<br />webpack将引入的js文件提升大屏它的引入者的顶部
```javascript
// main.js
export default "hello leo~";
// index.js
import str from "./main.js";
开启和不开启打包的文件大小不一样。
好处:
- 代码体积更小,因为函数声明语句中会产生大量代码,导致包的体积增大
- 代码在运行时会因为创建的函数作用域更少,内存开销也会变小
1、原理
Scope Hoisting 的实现原理其实很简单:分析出模块之间的依赖关系,尽可能将打散的模块合并到一个函数中,前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并。2、使用
1、webpack在mode为production时,会默认启用Scope Hoisting
2、手动
配置ModuleConcatenationPlugin插件new webpack.optimize.ModuleConcatenationPlugin();
二十二、代码分离
二十三、懒加载