从0基础到大牛-webpack深入浅出超强完整版(四)

你可能只需要这一个教程

webpack - Plugin

  loader和plugin都是webpack重要的组成部分,loader主要用于文件内的处理,而plugin主要用于文件间的处理,有时他们需要共同协作
  plugin的执行顺序与书写顺序无关,它通常是一个构造函数,挂载到webpack不同的生命周期中,等待执行

  • html-webpack-plugin

  html-webpack-plugin是我们最长的Plugin之一,它会帮我们管理html,
  下载插件npm install --save--dev html-webpack-plugin,配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {},
output: {},
mode: "development",
module:{},
plugins: [

// new HtmlWebpackPlugin()
// 默认在output文件下生成一个标题为Webpack App的html文件,并引入entry内的所有文件

new HtmlWebpackPlugin({
template : "./src/index.html"
})
// 指定html模板文件 会自动复制当前文件到output文件下,并引入entry内的所有口文件
]
};

  • clean-webpack-plugin

  想要每次新打包前清除output文件,以防止废弃文件占用内存空间,我们可以使用clean-webpack-plugin
  下载插件npm install --save--dev clean-webpack-plugin,配置如下

1
2
3
4
5
6
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(),
]
};

  • 指定服务器地址

  如有需要指定打包的服务器地址,可配置如下

1
2
3
4
5
6
7
module.exports = {
output: {
filename: '[name].js',
path: path.resolve(__dirname,'dist'),
publicPath: "http://xieyuxuan.cc" // 服务器地址
}
};

  打包后html引入的入口文件,都将会是publicPath的值+文件名

  • 错误调试 - sourceMap

  早期webpack打包后如有代码错误无法直接定位到源码,仅显示打包后的文件错误位置,这给开发调试造成了很大障碍
  sourceMap是一个映射关系表,能够将我们所有的源文件的映射到打包后的文件上。
  通过配置devtool,满足不同场景的调试需求
js module.exports = { devtool: 'none' // 默认值是none // source-map 会在output文件下生成一个 [output.filename].map的 映射文件 // inlne-source-map 将映射文件打入[output.filename] 内最底部 // cheap-module-source-map 生成环境中最常使用 生成[output.filename].map的 映射文件 // cheap-module-eval-source-map 开发环境中最常使用 // ... };

  • webpack-dev-server - 本地服务器

  webpack –watch命令可以实现文件更新检测,但这种方式无法满足我们的开发需要
  webpack-dev-server主要用于本地开发,满足我们的常规开发需求,大大提升我们工作效率
  它为我们开启一个本地服务器,可以实现热更新、跨域(服务器端没有跨域)、重定向等功能
  下载webpack-dev-server依赖npm install --save--dev webpack-dev-server,并在webpack.config.js中配置devServer属性

1
2
3
4
5
6
7
8
9
module.exports = {
entry: {},
output: {},
mode: "development",
module:{},
devServer:{
contentBase: './dist', // 服务器根文件地址
}
};

  在package.json中添加脚本,实现npm run dev开启本地服务

1
2
3
4
5
6
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server"
}
}

  终端执行npm run dev后,webpack会告诉我们webpack-dev-server为我们开启了一个地址为http://localhost:8080的服务
  此时观察dist文件,该目录下文件清空,但页面显示正常,文件更改后会自动刷新页面并重新执行
  dist下的文件不再存放在磁盘中,而是被放置在内存中

  webpack-dev-server其它常用配置如下

1
2
3
4
5
6
7
8
module.exports = {
devServer:{
contentBase: './dist', // 服务器根文件地址
open: true, // 自动打开页面
host: 'localhost', // 指定服务器地址 默认 localhost
port: 8080 // 指定端口号 默认8080
}
};

  实现HMR(热模块更新)

1
2
3
4
5
6
7
8
9
10
11
12
const webpack = require('webpack');

module.exports = {
devServer:{
contentBase: './dist',
open: true,
hot: true // 开启热模块更新
},
plugins: [
new webpack.HotModuleReplacementPlugin() // 配置热更新
]
};

  • TreeShaking

  有时我们定义了N个方法,但仅有部分方法被调用,不想让所有的方法都被打入,这时候我们就需要shaking一下
  将未被使用的 exported member 标记为 unused 同时在将其 re-export 的模块中不再 export
  这里必须使用ESmodule的引入方式
  webpack.config.js新增配置如下

1
2
3
4
5
6
7
8
module.exports = {
entry: {},
output: {},
mode: "development",
optimization: {
usedExports: true, // 开去tree shaking
},
};

  同时需要在package中新增配置,取消副作用

1
2
3
4
5
{
"name": "webpack-demo",
"version": "1.0.0",
"slideEffects": false
}

  虽然webpack设置了tree shaking,但是比如包中有一些配置,设定,日志等产生的副作用,会使得包文件依然会被打入
  如果你不想,可以设置slideEffects为false,或者通过数组指定
  我们在设置副作用时应当明确,这个包没有副作用或者不需要它们的副作用
  webpack会在线上shaking掉,我们的配置才会有效,而开发环境我们可以看到它的分析结果

  • 开发模式 和 生产模式

  开发模式 development 本地编写代码
  生产模式 production 用于打包完成后交给线上服务
  区分两种模式,实现不同环境的打包,现我们新建webpack.dev.js做开发配置,并将所有开发环境的配置保留,可参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');


module.exports = {
entry: { 'app' : './src/app.js' },
output: {
filename: '[name].js',
path: path.resolve(__dirname,'../dist'),
},
devtool: 'cheap-module-eval-source-map',
mode: "development",
devServer:{
contentBase: './dist',
hot: true,
},
optimization:{
usedExports: true,
},
module:{}, // 此处省略
plugins: [
new HtmlWebpackPlugin(
{template : "./src/index.html"}
),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};

  新建webpack.prod.js,做线上配置,并将所有线上环境的配置保留,可参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
entry: {'main' : './src/main.js'},
output: {
filename: '[name].js',
path: path.resolve(__dirname,'../dist'),
},
devtool: 'cheap-eval-source-map',
mode: "production",
optimization:{
usedExports: true
},
module:{}, // 此处省略
plugins: [
new HtmlWebpackPlugin(
{template : "./src/index.html"}
),
new CleanWebpackPlugin(),
]
};

  将webpack配置文件都放入根目录下的config文件夹内
  配置package.json,通过不同的命令执行不同的打包规则

1
2
3
4
5
6
7
8
{
"name": "webpack-demo",
"version": "1.0.0",
"scripts": {
"dev": "webpack-dev-server --config config/webpack.dev.js",
"build": "webpack --config config/webpack.prod.js"
}
}

  通过命令npm run dev与命令npm run build我们实现了不同环境下的打包
  虽然我们已经可以区分两种环境了,但是很明显配置文件中包含大量共同部分,现在我们新建webpack.common.js文件,提取公共部分