webpack简介
webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
核心概念
- 入口(entry)
- 输出(output)
- 模式(mode)
- loader
- 插件(plugin)
- 浏览器兼容性(browser compatibility)
- 环境(environment)
从0开始配置webpack项目
- 项目基础搭建/配置
mkdir -p webpack-dome
cd webpack-dome
// 初始化 packge.json
npm init
// 安装 webpack 依赖
npm install webpack webpack-cli --save-dev
根目录创建 index.html
新建 src,src/index.js
新建 webpack.config.js
const path = requere('path')
module.exports = {
mode: 'development', // 读取配置
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
}
}
基本配置完成,执行 npm run build 即可 生成 /dist 打包后的文件夹
npm run build
实际开发中,需要一个 dev 开发环境,这就用到了 webpack-dev-server
npm install -D webpack-dev-server
webpack.config.js 添加 相应 配置
npm run start
现在服务起来了,但是没有加载到index.html,因为打包中并没有处理 idnex.html 文件,所以现在就需要 html-webpack-plugin 来处理 index.html 文件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
filename: 'index.html'
}),
],
}
好了,到这步配置的时候,基本的项目就已经搭建起来了,我们实际的项目中,需要处理的东西有很多,比如es6/less等文件的转换,这样就需要使用 loader 和 plugin 了
- loader
在介绍loader之前,我们要搞清楚loader是什么,为什么会需要 loader。
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加载)" 模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的得力方式。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS 文件!
loader的设计原则
- 职责单一:每个loader 只做一件事
- 链式调用:第一个loader接收到的是源文件的内容,后续loader都是接收到的是上一个loader 返回的处理结果,webpack 会按顺序链式调用每个 loader
- 统一原则:遵循 Webpack 制定的设计规则和结构,输入与输出均为字符串,各个 Loader 完全独立,即插即用
- 无状态:在多次模块的转化之间,我们不应该在 loader 中保留状态。每个 loader 运行时应该确保与其他编译好的模块保持独立,同样也应该与前几个 loader 对相同模块的编译结果保持独立
好了,上面介绍完了loader,现在咱们手写一个 loader,其实每个 laoder 就是 webpack 中的一个独立的代码块,说白了就是一个函数
// replaceLoader.js
// 字符串替换
module.exports = function (source) {
// this.query 可读取 webpack 配置 参数
return source.replace('world', 'webpack')
}
loader 创建好了,现在我们只需要在 webpack.config.js 配置文件中使用就好了
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
use: path.resolve(__dirname, './replaceLoader.js'),
}
]
},
}
当我们再启动文件时候,打印出来的就是 替换后的 日志了。
当然在我们实际的开发中,可能会需要 对 loader 添加一些 参数,让 loader 读取 我们的 配置
use: [
{
loader: path.resolve(__dirname, './replaceLoader.js'),
options: {
name: 'webpack-query'
}
}
]
- plugin
插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!插件目的在于解决 loader 无法实现的其他事。
plugin是一个具有 apply 方法的 JavaScript 对象。apply 方法会被 webpack compiler 调用,并且在 整个 编译生命周期都可以访问 compiler 对象。
// 自定义 plugin
const pluginName = 'ConsoleLogWebpackPlugin'
class ConsoleLogWebpackPlugin {
apply(compiler) {
compiler.hooks.compile.tap(pluginName, (compilation) => {
console.log('====================================');
console.log('webpack plugin 生效了');
console.log('====================================');
})
}
}
module.exports = ConsoleLogWebpackPlugin