前言
在前端开发环境中,一个项目在开发时态(Devtime)和运行时态(Runtime)的侧重点不同
开发时态(Devtime):
- 模块划分的越细越好
- 支持多种模块化标准
- 支持npm或其它包管理器下载的模块
- 能够解决其它工程化的问题
运行时态(Runtime):
- 文件越少越好
- 文件体积越小越好
- 代码内容越乱越好
- 能够解决浏览器兼容性
- 能够解决其它运行时的问题(例:执行效率问题)
由于开发时态和运行时态有着的巨大差异,所以,我们需要有一个工具,这个工具能够让开发者专注于开发时态项目开发,然后利用这个工具将开发时态编写的代码转换为运行时态需要的内容,这样的工具,叫做构建工具
1、Webpack核心功能
wbpack简介
简介:
webpakc是基于模块化的构建(打包)工具,它将一切视为模块,通过一个开发时态的入口模块为起点,分析出所有的依赖关系,然后经过编译等一系列过程,最终生成运行时态所需的文件。特点:
- 为前端工程化而生:致力于解决前端工程化,让开发者专注于编写业务代码,而工程化过程交给webpack来处理。
- 简单易用:支持零配置,开箱即用。
- 强大的生态环境:webpack本身的功能并不多,但它提供了可以扩展其功能的机制,使得很多第三方库可以融入到webpack。
- 基于nodejs:由于webpack在编译过程中需要读取文件,因此它是运行在node环境中的。
- 基于模块化:webpack在编译过程中需要分析依赖关系,通过模块化导入语句进行分析,因此它支持各种模块化标准。
webpack的安装与使用
webpack通过npm安装,它提供两个包:
- webpack:核心包,包含了webpack构建过程中需要用到的所有api。
- webpack-cli:提供了一个cli命令,用来调用核心包中的api。
// 全局安装:全局使用webpack命令,但是无法为不同项目提供不同webpakc版本 npm install webpack webpack-cli -g // 局部安装:推荐使用,每个项目都使用自己的webpack版本进行构建 npm i webpack webpack-cli
开始打包:
npx webpack
默认情况下,webpack会使用 ./src/index.js 作为入口文件分析依赖关系,打包到 ./dist/main.js 文件中
webpack的配置文件
配置文件:通过CommonJS模块导出一个对象,对象中的各种属性对应不同的webpack配置
webpack-cli支持很多参数,例如 –mode 配置webpack运行环境。但是更多时候我们会使用配置文件来控制webpack。配置文件和CLI参数冲突,以参数为准
默认情况下,webpack会读取 webpack.config.js 文件作为配置文件。可以通过CLI参数 –config ‘filename’ 来指定某个配置文件。
核心配置属性:
规则:
- name:chunkname
- hash:总资源的hash,通常用于解决缓存问题
- chunkhash:chunkhash
- id:chunkid
1. entry(入口):字符串 | 对象,配置编译过程的chunk
module.exports = {
entry: './src/index.js' // 指定一个入口起点
}
module.exports = {
entry: { // 指定多个入口起点
main: './src/main.js',
index: './src/index.js'
}
}
2. output(出口):对象,针对资源列表的文件名和路径的配置
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'), // 输出路径
filename: '[name].[hash:5].js' // 输出文件名
}
}
3. loader(加载器):本质是一个函数,用于将源码字符串转换成另一个源码字符串返回
// loader完整配置
module.exports = {
module: { // 针对单个模块的配置
rules: [ // 匹配模块规则
test: /\.js$/, // 正则匹配
use: [ // 匹配到后要使用的loader模块
{
loader: '模块路径', // loader模块路径
options: { // 向对应loader传递的额外参数
}
}
]
]
}
}
// loader简化配置
module.exports = {
module: { // 针对单个模块的配置
rules: [ // 匹配模块规则
test: /\.js$/, // 正则匹配
use: ['模块路径1', '模块路径2']
]
}
}
4. plugins(插件):本质是一个带有apply方法的对象
module.exports = class MyPlugin{
apply(compiler){
// compiler对象在构建初始化阶段创建,提供大量的钩子函数
// 构建工作由compiler对象内部创建的compilation完成
compiler.hooks.事件名称.事件类型(name, function(comilation){
// 事件处理函数
})
}
}
const MyPlugin = require('./plugin/MyPlugin.js');
module.exports = {
plugins: [
new MyPlugin()
]
}
其它配置属性
context:使用context配置作为基准路径
const path = require('path');
module.exports = {
// 入口和loaders的相对路径会以context作为基准路径
context: path.resolve(__dirname, 'app');
}
library:将立即执行函数结果暴露
libraryTarget:暴露入口的导出结果
libraryTarget可用值
module.exports = {
library: 'abc', // 变量值
libraryTarget: 'var' // 变量名
}
target:打包结果要允许的环境
target可用值
module.exports = {
target: 'web' // 打包后的代码允许在web环境中
}
module.noParse:不解析正则表达式匹配的模块
module.exports = {
module: {
noParse: /jquery|lodash/ // 忽略匹配的模块,提高性能
}
}
extensions:解析模块时,遇到无具体后缀的导入语句
module.exports = {
extensions: ['.js', 'json']; // 该配置会依次测试它的后缀名
}
alias:路径别名
const path = require('path');
module.exports = {
alias: {
'@': path.resolve(__dirname, 'src'),
'_': __dirname
}
}
externals:排除配置的模块源码,并使用对应值代替
module.exports = {
externals: {
jquery: '$',
lodash: '_'
}
}
// 未配置externals前
(function(){
...
})({
"./src/index.js": function(module, exports, __webpack_require__){
__webpack_require__("jquery")
__webpack_require__("lodash")
},
"jquery": function(module, exports){
//jquery的大量源码
},
"lodash": function(module, exports){
//lodash的大量源码
},
})
// 配置externals后
(function(){
...
})({
"./src/index.js": function(module, exports, __webpack_require__){
__webpack_require__("jquery")
__webpack_require__("lodash")
},
"jquery": function(module, exports){
module.exports = $;
},
"lodash": function(module, exports){
module.exports = _;
},
})
stats:控制构建过程中需要控制台输出的内容
webpack区分环境
由于生成环境和开发环境中的webpack配置有不同区别,为了区分webpack配置允许是一个函数,函数的返回结果作为配置内容
module.exports = env => { // 调用函数时会传入一个参数env,该参数来自webpack-cli命令中的参数
return {
// 配置内容
}
}
npx webpack --env abc // env: 'abc'
npx webpack --env.abc=1 // env: {abc: 1}