Webpack初体验

webpack 作为一个现代的 JS 应用程序的静态打包工具(module bundler) 是没一个前端都绕不开的必啃项目。为了防止遗忘所以在学习的过程中我们做一些相应的笔记,以此来完善知识体系

提要

webpack:静态解析。项目完成后从入口开始解析,将依赖项打包,非依赖项不进行处理

glup:按照某种规则对文件进行匹配,成功则执行对应流程,一个一个进行处理

mode:开发模式 production

entry:入口文件

output:最终打包完成的bundle放至何处

loader:用loader处理非 JS 文件,将其转化为webpack所能处理的有效模块(JS、JSX)

plugins:打包优化、压缩、重新定义环境中的变量等等。。。

加载非JS文件

​ 由于webpack无法解析非 JS 文件,所以我们需要对其进行预处理,将其解析为webpack可理解的形式。

CSS文件

我们需要两个loadercss-loaderstyle-loader

1
npm i -D style-loader css-loader

此后就需要更改我们的配置项文件(webpack.config.js)啦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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"] // 处理过程从右向左,先执行 css-loader 再执行 style-loader
}]
}
};

初始工具

1
2
3
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev

webpack-cli用于再命令行中运行webpack

一般来说我们会选择局部而非全局安装webpack,这样会有固定的版本号,以至于我们更新时不会将某些依赖项改变

使用教程

webpack.config.js中的配置项

webpack.config.js中一般是用来存储配置项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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"] // 处理过程从右向左,先执行 css-loader 再执行 style-loader
}]
}
};

​ 此例中我们通过use字段规定了处理以.css结尾的文件的处理方式。由于webpack无法解析除去 JS、JSX语法之外的其他语言,所以在此我们需要使用css-loader将其解析为webpack可处理的语言,再交由style-loader将其渲染至页面上。

​ 而具体引入方法就是将该css文件引入至将要引入页面的 JS 文件之中去

module中其他配置项
  • module.noParse:此类型为了防止webpack解析那些与正则相匹配的文件。举个栗子,我们不需要对jquerylodash等文件进行解析

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

      module.exports = {
      entry: "./src/index.js",
      output: {
      filename: "bundle.js",
      path: path.resolve(__dirname, "dist")
      },
      module: {
      noParse: /jquery|lodash/
      // 写成函数样式的也可以
      // noParse: function(content){
      // return /jquery|lodash/.test(content);
      //}
      }
      };
    • 当然我们也可以采用另一种写法,毕竟

  • module.rules:这个的话上边的例子有,参照那个就好啦

  • module.rulerules中的具体配置项。其test项既可以是字符串(目录绝对路径或是文件绝对路径)、正则表达式、函数(返回为true的就可以匹配),亦可以是对象(匹配所有属性。每一个属性都有一个定义行为)和条件数组(至少一个匹配条件)

    • Rule.test:既可以为一个正则、函数,亦可以是一个正则数组或条件数组
    • Rule.include:匹配特定条件
    • Rule.exclude:排除特定条件
    • Rule.and:必须匹配数组中的所有条件
    • Rule.or:匹配数组中的任一条件
    • Rule.not:必须排除某条件
    • Rule.use:应用于模块指定使用一个loader

我们举个例子。由于node_module文件夹中一般来讲发布到线上后会从 CDN 上获取资源,所以不需要对其进行打包,自然也是忽略掉。折至webpack.config.js中的配置为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
....
module: {
rules: [
{
test: [/\.css$/, /\.js$/, /\.html$/, /\.ejs$/],
exclude: [
path.resolve(__dirname, "node_modules")
],
use: ["style-loader", "css-loader"]
}
]
}
};

Sourse Map

经过打包后的文件都被封装过,而希望找到其最初始的位置我们需要Source Map

比如,在css-loadersass-loader中我们都可以通过options配置项启用sourcemap

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: {
rules: [
{
test: /\.(sc|sa|c)ss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader",
options: {
sourceMap: true
}
}, {
loader: "sass-loader",
options: {
sourceMap: true
}
}]
}
]
}
};

PostCSS

是一个 CSS 预处理插件,可以帮助我们:

  • 给 CSS3 的属性添加前缀
  • 样式格式校验(stylelint
  • 实现 CSS 模块化,防止 CSS 样式冲突
1
npm i -D postcss-loader autoprefixer

举个栗子,我们上方在完成.sass的解析后在让css-loader进行解析之前需要对一些 CSS3 特性加上前缀。那么就在 Rule.use 项中添加一个配置项

1
2
3
4
5
6
7
8
9
10
{
loader: "postcss-loader",
options: {
ident: "postcss",
sourceMap: true,
plugins: loader => {
require("autoprefixer")({ browsers: {'> 0.15% in CN' } }) //添加前缀
}
}
}