WebPack 学习
参考资料
概述
什么是 webpack
webpack 是一个前端项目构建工具(打包工具),提供 代码压缩混淆、处理 js 兼容性问题、性能优化 等功能
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
前端模块化开发
传统开发模式的主要问题
- 命名冲突
- 文件依赖
而引入模块化的目的就是为了解决这个问题,就是将单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块;在 ES6 出来之前 JavaScript 社区有三种常见的模块化规范 AMD、CMD、CommonJS
但是,这些社区提出的模块化标准,还是存在一定的差异性与局限性、并不是浏览器和服务器通用的模块化标准,例如:
- AMD 和 CMD 适用于浏览器端的 Javascript 模块化
- CommonJS 只适用于服务器端的 Javascript 模块化
所以,ES6 语法规范中,在语言层面上定义了模块化规范,是浏览器与服务器端通用的模块化开发规划
例如 ES6 模块化规范中定义:
- 每个 js 文件都是一个单独的模块
- 导入模块成员使用 import 关键字
- 暴露模块成员使用 export 关键字
webpack 基础使用
配置环境
先安装 webpack
# --save-dev 可以直接使用 -D 参数
# --save 可以直接使用 -S 参数
npm install -–save-dev webpack webpack-cli
添加配置文件
在根目录创建一个 webpack.config.js 的文件
参考资料 webpack 中文文档
webpack.config.js 配置文件各项参数
- entry: 入口文件,指定WebPack 用哪个文件作为项目的入口
- output:输出,指定WebPack把处理完成的文件放置到指定路径
- module:模块,用于处理各种类型的文件
- plugins:插件,如热更新、代码重用等
- resolve:设置路径指向
- watch:监听,用于设置文件改动后直接打包
- mode:指定构建模式,
development表示开发模式,还有一个production表示正式环境,区别就是development不会压缩混淆代码
入口 (entry)
入口会指示 webpack 应该使用哪个文件来作为构建其内部依赖图的开始。
进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。在 webpack 中入口有多种方式来定义,如下面例子:
单个入口(简写)语法:
module.exports = {
entry: "./src/main.js"
}
输出 (output)
output 属性会告诉 webpack 在哪里输出它创建的 bundles ,以及如何命名这些文件,默认值为 ./dist
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, 'dist')
}
}
加载器 (loader)
loader 让 webpack 可以去处理那些非 JavaScript 文件( webpack 自身只理解 JavaScript )。loader 可以将所有类型的文件转换为 webpack 能够有效处理的模块,例如,开发的时候 使用 ES6 ,通过 loader 将 ES6 的语法转为 ES5 ,如下配置:
const path = require('path');
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
// 使用
test: /\.js$/,
// exclude 为排除项,表示 babel-loader 不需要处理 node_modules 中的 js 文件
exclude: /node_modules/,
// 表示使用 'babel-loader' 加载器来处理 .js 文件;(loader: "babel-loader" 这种已经废弃了)
use: 'babel-loader',
options: [
presets: ["env"]
]
}
]
}
}
下面会专门讲这个
插件 (plugins)
参考文档 HtmlWebpackPlugin
loader 被用于转换某些类型的模块,而插件则可以做更多的事情。包括打包优化、压缩、定义环境变量等等。插件的功能强大,是 webpack 扩展非常重要的利器,可以用来处理各种各样的任务。使用一个插件也非常容易,只需要 require() ,然后添加到 plugins 数组中。
下面以这个 html-webpack-plugin 为例;html-webpack-plugin 插件是用于编译 Webpack 项目 中的 html 类型的文件,如果直接将 html 文件置于 ./src 目录中,用 Webpack 打包时是不会编译到生产环境中的。因为 Webpack 编译任何文件都需要基于配置文件先行配置的。
npm install --save-dev html-webpack-plugin
//webpack.config.js
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
home: path.resolve(__dirname, './src/app.js')
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
plugins: [
new htmlWebpackPlugin({
// template 指定你生成的文件所依赖哪一个 html 文件模板
template: './src/index.html',
filename: 'index.output.html'
})
]
}
添加快捷命令
在 package.json 配置文件中的 scripts 节点下新增 dev 脚本
"scripts": {
"dev": "webpack" // script 节点下的脚本可以通过 npm run 执行
},
执行命令启动
npm run dev
可以看到输出如下,表示把 ./src/index.js 打包成 main.js 文件了
> webpack
Hash: 76fcf8b80028b8893c91
Version: webpack 4.44.1
Time: 328ms
Built at: 2020-08-03 23:55:00
Asset Size Chunks Chunk Names
main.js 322 KiB main [emitted] main
Entrypoint main = main.js
[./src/index.js] 166 bytes {main} [built]
+ 1 hidden module
配置自动打包工具
安装 webpack 的自动打包工具,使之能监听代码修改了自动打包
npm install webpack-dev-server -D
然后在 package.json 配置文件中的 scripts 节点下修改 dev 脚本
// --open 打包完成后自动打开浏览器界面
// --host 配置 IP 地址
// --port 配置端口
"scripts": {
// 在 webpack5 之后这个 webpack-dev-server 启动改成了这个
"dev": "webpack serve"
},
生成预览页面
安装生成预览页面的插件(就是访问项目根目录就能自动访问到 src/index.html 的信息)
原理就是复制一份指定路径的文件到内存里,访问项目根目录时,把这个内容返回出去
npm install html-webpack-plugin -D
然后修改 webpack.config.js 配置文件,添加如下配置信息
const HtmlWebpackPlugin = require('html-webpack-plugin');
const htmlPlugin = new HtmlWebpackPlugin({
// 创建插件的实例对象
template: './src/index.html', // 指定要用到的模板文件
filename: 'index.html' // 指定生成的文件名称,该文件存在于内存中,在目录中不显示
})
再在 webpack.config.js 配置文件向外暴露配置对象
module.export = {
plugins: [htmlPlugin] // plugin 数组用于暴露 webpack 打包用到的一些插件
}
使用案例
const path = require('path');
module.exports = {
mode: "development", // "production" | "development"
// 选择 development 为开发模式, production 为生产模式
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
options: [
presets: ["env"]
]
}
]
},
plugins: [
...
]
}
实现一个隔行变色的效果
<ul>
<li>这是第1个li</li>
<li>这是第2个li</li>
<li>这是第3个li</li>
<li>这是第4个li</li>
<li>这是第5个li</li>
<li>这是第6个li</li>
</ul>
import $ from 'jquery'
$(function(){
// 奇数行
$('li:odd').css('backgroundColor','pink');
// 偶数行
$('li:even').css('backgroundColor','lightblue');
})
但是如果向上面那样直接使用 import 导入模块是执行不了的
npm run dev
使用 webpack 打包后更改成 打包后的 js 就行了
<script src="../dist/main.js"></script>