webpack 学习一:基本概念

2020 年 06 月 09 日

admin
webpack

webpack 是一个 js 静态模块打包器。当 webpack 处理应用程序时,它会递归构建一个依赖关系图,该图映射项目中所用到的每个依赖模块,并将他们打包成一个或多个 bundle。今天我们就来聊聊 webpack 的 四个核心基本概念:entryoutputloaderplugins

entry

开头说,webpack 打包需要递归构建一个依赖关系图,那么这个依赖关系图从哪里开始构建呢?就是从 entry 入口文件开始分析,递归构建的。

entry 入口,指示 webpack 以哪个文件或模块为起点,构建其依赖关系图,默认是 ./src/index.js。webpack 将找出这个文件所依赖的模块(直接或者间接依赖的),经过合适的处理(loader),将其打包到相应的 bundle 文件中。

entyr 的配置写法看起来好像是三种,字符串对象数组,其实只有一种,字符串写法与数组写法只不过是对象写法的简写形式。

对象写法

先来看看,对象写法。

module.exports = {
  entry: {
    <key>: <value>
    ...
  }
}

如上面代码所示,entry 中的 每个 key value 对,代表一个入口 。

<key> 的形式可以是普通的字符串,也可以是路径字符串

普通字符串

module.exports = {
  entry: {
     'my-custom-name': './src/index.js'
  }
}

将生成如下目录:

./dist
├── index.html
└── my-custom-name.js

路径字符串,多页面配置可能会用到这种写法。

module.exports = {
  entry: {
     'temp/pc/big-wheel': './src/index.js'
  }
}

将生成如下目录:

./dist
├── index.html
└── temp
    └── pc
        └── big-wheel.js

<value> 的值 合理的 node require 函数参数字符串,比如:./src/index.jslodash;也可以是数组,比如 ['jquery', 'lodash']。数组中的文件一般是没有相互依赖关系的,但是又处于某些原因需要将它们打包在一起

module.exports = {
  entry: {
     app: './src/index.js',
     vendor: ['jquery', 'lodash']
  }
}

生成目录如下

./dist
├── app.js
├── index.html
└── vendor.js

字符串写法

module.exports = {
  entry: './src/xx/x.js'
}
// 等价于
module.exports = {
  entry: {
    main: './src/xx/x.js'
  }
}

数组写法

module.exports = {
  entry: ['./src/index.js', 'lodash']
}
// 等价于
module.exports = {
  entry: {
    main: ['./src/index.js', 'lodash']
  }
}

output

output 指示 webpack 将 bundle 文件,输出 到哪里,以及如何 命名 这些文件,默认输出到 ./dist 目录,命名为 main 。我们可以指定 pathfilename 来自定义输出位置与文件名。

module.exports = {
 entry: {
    app: './src/index.js',
  },
  output: { 
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
}

生成以下目录:

./dist
├── bundle.js
└── index.html

当有多个入口的时候,就需要 修改 filename 的写法了,不然会报 Multiple chunks emit assets to the same filename bundle.js (chunks 0 and 1)

filename 的写法有以下几种

bundle.js

如上面所示,适用于单个入口的情况。

[name].bundle.js

使用入口名称

module.exports = {
 entry: {
    app: './src/index.js',
    vendor: ['jquery', 'lodash']
  },
  output: { 
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
}

生成以下目录:

./dist
├── app.bundle.js
├── vendor.bundle.js
└── index.html

[id].bundle.js

使用内部 chunk id

filename: "[id].bundle.js"
./dist
├── 0.bundle.js
├── 1.bundle.js
└── index.html

[name].[hash].bundle.js

使用每次构建过程中,唯一的 hash 生成

filename: "[name].[hash].bundle.js"
./dist
├── app.2255f3bf5376173d45e9.bundle.js
├── vendor.2255f3bf5376173d45e9.bundle.js
└── index.html

[chunkhash].bundle.js

使用基于每个 chunk 内容的 hash。在优化 缓存的时候,可能用到。

filename: "[chunkhash].bundle.js"
├── 0d61ecf7529739f49dca.bundle.js
├── a680c26e174cde5631d1.bundle.js
└── index.html

loader

loader 的功能就是 “翻译”,将非 js 类型的文件,经过适当的处理,输出 webpack 能够处理的有效模块。

通过两个字段来配置:test 是一个正则,表示匹配哪些类型的文件;use 表示用什么 loader 处理。

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader', 'css-loader'] },
      { test: /\.(png|svg|jpg|gif)$/, use: 'file-loader' }
    ]
  }
}

plugins

plugins 可以用于执行范围更广的任务,插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。

在 webpack 整个打包过程中,会经历不同的阶段,每个阶段可能需要做一些处理,会暴露出一些类似于声明周期这样的钩子,供 插件 去处理。

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

参考链接

令人困惑的webpack之entry

0 / 500
技术是第一生产力