webpack4读书笔试(一)

今日鸡汤: 优秀的工程师 = 主人翁意识 + 追求卓越的精神

写这篇文章的目的是因为webpack4的出现,并且发现以前有很多东西其实一直都在用,但是没有很细的了解里面的东西,本篇文章主要梳理下相关内容。

想要把自己知道的和不知道的,都系统的总结下。

webpack模块打包工具 - a static module bundler


webpack4如何做到更快

需要nodejs版本新 + webpack版本新

webpack 会利用新版 Nodejs 的特性进行更好的优化


–save-dev = -D

1
2
npm install webpack webpack-cli --save-dev
npm install webpack webpack-cli -D

npx和npm的区别

npx会去当前文件夹下的 node_modules 找命令
npm会去全局找命令,如果找不到,才会去当前的node_modules下

1
2
npm webpack -v 是全局的 webpack 版本
npx webpack -v 是当前项目内使用的 webpack 版本


安装某个版本的webpack

1
2
3
4
// 查看webpack的历史version信息
npm info webpack
// 安装指定版本的version
npm install webpack@version -D

webpack查询配置路径

webpack 需要指定入口文件

  1. npx webpack index.js入口文件为 index.js, webpack4index.js作为入口。
  2. 若不指定入口,webpack则取找 webpack.config.js 文件,读取配置文件中的entry
  3. 若不指定入口并且没有webpack.config.js文件,则报错。
  4. 如果不想用 webpack.config.js,可以使用npx webpack --config webpackconfig.js来指定配置文件。

最简单的 demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const path = require('path');

module.exports = {
entry: './path/to/my/entry/file.js',
output: {
// 注意这里是绝对路径,webpack4默认是这个dist路径,如果你不写的话
path: path.resolve(__dirname, 'dist'),
// filename 可以指定生成的文件的名称
filename: 'my-first-webpack.bundle.js',
// filename: '[name].bundle.js',
// filename: '[name].js',
// filename: '[hash].bundle.js' //b4
// filename: '[id].bundle.js'
// filename: '[chunkhash].bundle.js',ed
// filename: '[contenthash].bundle.js'
}
};

如下分别是对应的生成结果:

相关filename配置

为什么 [name].js生成的对应是 main.js呢?因为entry: 'xxx' = entry: {main: 'xxx'}, 省略了名称为 main 的写法。

output还有很多options,可以参照官方文档来看。output

注意一般情况我们不会把 output 里的 filename 直接设置为 bundle.js,这样如果又多个entry,最后都被命名为 bundle.js,webpack就会报错了。一般情况下,我们就设置为[name].bundle.js就挺好的。

output 里面还有我们经常用到的 publicPath, 用于设置静态资源的地址,比如我们可以设置它为cdn的域名路径。//cdn.com/h5,最后html文件中生成的路径可能就是<script type="text/javascript" src="//cdn.com/h5/main.bundle.js"></script>这种我们需要的路径。


webpack4 mode

mode: development/production 主要区别在是否压缩。如果配置中不写,默认是 production,并且会有 warning。

webpack打包后控制台信息:
hash 本次打包的唯一一个hash值
Version webpack的版本
Time 打包耗时
Asset 打包后的文件名
Size 打包后的文件大小
Chunks 打包后文件对应的id
Chunk Names 每一个打包后文件对应的打包文件名字

控制台信息

有的时候有警告是因为没有配置打包的模式:mode,mode有两种设置:默认的是production,代码会被压缩,还可以是development,代码不压缩


loader

webpack 默认只知道打包js文件,png,css 等是不知道应该怎么处理的。

所以对于 png, css, vue 这一类的模块资源,我们就得在webpack配置中,告诉webpack怎么打包。具体就是放在 module 里,配置相关的rule,然后用相关的 loader 去处理

因此可以理解为:loader就是打包方案,对非js结尾模块,要用loader进行处理。


处理图片的loader

这里举例两种处理图片的loader, file-loaderurl-loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
}
}
}
]
}
}

更多相关配置,要参考 webpack loader 一节。标注两个经常用到的点:

  1. name标明你要生成图片的名称,比如[name].[ext]就是原文件名输出,[name]_[hash].[ext]就是名称+hash后的文件,如:1_752df31a916202d90967bed23f618507.png
  2. outputPath标明你要把文件放在哪个目录下,如dist/images下。设置这里outputPath还可以是个函数。如下
1
2
3
4
5
6
7
outputPath: (url, resourcePath, context) => {
if (/images/.test(context)) {
return `image_output_path/${url}`;
}

return `output_path/${url}`;
}

里面 file-loader 做了两件事情:

  1. 移动文件到dist文件下
  2. 得到图片名称,作为返回值,返回名称

注意file-loader不一定是针对图片,对txt等其他文件也是一样的。

还有一个是 url-loader, url-loaderfile-loader

url-loader可以把图片转换成base64编码,并放于js中。这样的好处是节约了一次http请求,坏处是如果图片太大,转换成的base64太大,就会导致js太大,影响页面的加载和执行。

因此正确使用 url-loader 的形式是如果图片很小,比如是个 icon, 那么用 url-loader 就太适合了。

比如我们可以这么来写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module: {
rules: [
{
test: /\.(png|jpg|jpeg|)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
}
]
}

如果文件比 20k 要大, 则url-loader会自动使用file-loader来处理文件。


处理css的loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
//...

module: {
rule: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
}
]
}
}

注意:loader的执行顺序是从下到上,从右到左,如上面就是先执行 postcss-loader, 最后执行style-loader。其中区别解释如下:

  1. style-loader 用来把 style 节点添加到 dom 上的,即负责把css代码挂载到中间。
  2. css-loader 用来把一个或多个css文件合并成一段css代码,比如有多个css文件,可以合成一个。
  3. postcss-loader 可以用来帮我们做css添加前缀,或者压缩优化css等工作。一般postcss-loader需要建立一个postcss.config.js用来写相关配置。如:
1
2
3
4
5
module.exports = {
plugins: [
require('autoprefixer')
]
}

解释css-loader部分参数的含义:

  1. importLoaders: 2保证不管是js中引用css文件,还是js中引用js文件,都要从上到下依次进行使用loader, 而不是只有index里面import的css被从下到上执行,而css里面引用的文件不会从下到上执行。
  2. modules: true使css支持模块化引用,如不想让某个css文件作用于全局。
    1
    2
    3
    import style from './1.css'

    img.classList.add(style.avatar)

这样,style中的样式可以只针对某些地方生效,而不是全局生效。其实我最经常用的是 import './1.css' 作用于全局,因为我们的样式都是重构统一给到的。


处理字体文件的loader

当我们再css、sass文件中引入了字体文件,如eot, ttf, svg,如果我们不告诉webpack,webpack会报错

1
2
3
4
@font-face {
font-family: "iconfont",
src: url('./font/iconfont.eot')
}

因为webpack并不知道如何去处理并引入这些文件,所以我们需要给这些结尾的文件(字体),使用 file-loader,如:

1
2
3
4
5
6
{
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader'
}
}

除了上述loader,还有其他如 xml-loader, cvs-loader 等,可以参考着一节。loader

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 const path = require('path');

module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
- module: {
- rules: [
- {
- test: /\.css$/,
- use: [
- 'style-loader',
- 'css-loader'
- ]
- },
- {
- test: /\.(png|svg|jpg|gif)$/,
- use: [
- 'file-loader'
- ]
- },
- {
- test: /\.(woff|woff2|eot|ttf|otf)$/,
- use: [
- 'file-loader'
- ]
- },
- {
- test: /\.(csv|tsv)$/,
- use: [
- 'csv-loader'
- ]
- },
- {
- test: /\.xml$/,
- use: [
- 'xml-loader'
- ]
- }
- ]
- }
};


总结

本篇主要跟 loader 相关。理解webpack是任何时候可以把任何类型的文件都当成模块去处理。

理解 loader 是为了告诉 webpack 什么样的文件,应该用什么样的东西处理。

即loader 是打包方案,是告诉 webpack 非 js 结尾的应该怎么处理。