一、安装 Node Webpack Webpack-cli
1.1 Node 去官网下载安装
1.2 全局安装 webpack webpack-cli
当你 React 项目用的是 webpack 5.x, Vue 项目用的是 4.x, Angular 用的是 3.x
此时你就需要局部安装,不然多个项目共用一个全局的 webpack 时,就会出现版本冲突问题。
npm i webpack webpack-cli -g
npm i webpack webpack-cli -D
本文截止 2021 年 9 月 7 日 23:44:25 版本信息为
名称 | 版本 |
---|
Webpack | v5.52.0 | Webpack-Cli | v4.8.0 | Node | v14.16.1 | Npm | v7.20.6 |
二、初识 Webpack
2.1 官方文档地址
英文官网:https://webpack.js.org 中文官网V4:https://v4.webpack.docschina.org 中文官网V5:https://webpack.docschina.org
2.2 入口
webapck 默认入口文件为 src/index.js
通过 entry 可以修改入口位置
module.exports = {
entry: "./src/index.js",
};
2.3 出口
webapck 默认出口文件为 dist/main.js
通过 output.filename 可以修改出口位置
module.exports = {
output: {
filename: "./dist/main.js",
},
};
2.4 第一次打包 执行 webapck
注: 使用 npx webpack 来使用局部的 webpack
原文件目录:
index.html 引入 src/index.js
src/index.js 引入 format.js And math.js
├── index.html
├── package.json
└── src
├── index.js
└── js
├── format.js
└── math.js
最终在控制台输入webpack ,则生成以下目录
├── dist
| └── main.js
├── index.html
├── package.json
└── src
├── index.js
└── js
├── format.js
└── math.js
此时注意,index.html 并没有自动引入dist/main.js ,原因是需要配置插件,本文后边会做说明。
当前,你可以在index.html 手动引入dist/main.js 看一下js 文件有没有被正常打包。
2.4 package.json 脚本
在package.json 文件的scripts 中配置对应脚本,使用npm run 即可运行指定的脚本,注意,在此处执行的命令默认是都会从node_modules/.bin 下去查找命令的,即使用的是局部的版本。
"scripts": {
"build": "webpack"
},
2.5 使用配置文件
配置文件的默认名称是 webpack.config.js ,如果你的项目根目录存在该文件,则webpack 在打包的时候会自动载入该配置文件,该文件的基本导出语法如下:
注:webpack 是在 Node 环境下运行,Node 使用的是 CommonJS 规范,所以需使用 module.exports
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
};
2.6 指定配置文件的名称
如果你不想使用 webpack.config.js 这个名称,可以在package.json 文件的启动脚本处指定配置文件,具体如下:
–config 后边就是你的自定义文件名称
"scripts": {
"build": "webpack --config wb.config.js"
}
三、webpack 配置 loader
3.1 配置 CSS
正确显示 CSS 需要配置两个 loader ,分别是style-loader css-loader
css-loader 只是负责将.css 文件进行解析,并不会将解析之后的 css 插入到页面中;
如果我们希望再完成插入 style 的操作,那么我们还需要另外一个loader ,就是style-loader ;
3.1.1 安装
npm i style-loader css-loader -D
3.1.2 配置
具体配置如下:
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{ loader: "css-loader" },
],
},
],
},
};
3.2 配置 less
同样的道理,需要使用 loader 来处理,这里使用到一个less 和less-loader .
3.2.1 安装
npm i less less-loader -D
3.2.2 配置
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{ loader: "css-loader" },
],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
};
3.3 PostCSS 工具
什么是 PostCSS 呢?
- PostCSS 是一个通过 JavaScript 来转换样式的工具;
- 这个工具可以帮助我们进行一些 CSS 的转换和适配,比如自动添加浏览器前缀、css 样式的重置;
- 但是实现这些功能,我们需要借助于 PostCSS 对应的插件;
如何使用 PostCSS 呢?主要就是两个步骤:
- 第一步:查找 PostCSS 在构建工具中的扩展,比如 webpack 中的 postcss-loader;
- 第二步:选择可以添加你需要的 PostCSS 相关的插件;
通过 PostCSS 你可以实现以下效果:
div {
color: #12345678;
user-select: none;
}
div {
color: rgba(18, 52, 86, 0.47059);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
在webpack 中使用postcss 大概思路:
postcss-loader => postcss => 查找 postcss 的插件实现对应功能
postcss-loader => postcss => 预设(本身也是插件,集成诸多功能在一起叫它预设)
常用插件(陆续补充):
插件名 | 作用 | 安装 |
---|
autoprefixer | 自动添加浏览器前缀 | npm i autoprefixer -D |
3.3.1 安装
插件方式使用 (不推荐,很少用 功能单一配置麻烦):
npm i postcss postcss-loader autoprefixer -D
预设方式使用(推荐,包含诸多功能,且内置 autoprefixer):
npm i postcss postcss-loader postcss-preset-env -D
3.3.2 配置详情
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{ loader: "css-loader" },
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
require("postcss-preset-env"),
],
},
},
},
],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
};
3.4 处理图片资源 与 base64
使用 file-loader 或者 url-loader url-loader 和 file-loader 的工作方式是相似的,但是可以将较小的文件,转成 base64 的 URI。
注意:最新版的css-loader 也会对我们的图片资源打包,如果不想用css-loader 的图片打包功能,可把它关闭,或者安装之前的 css-loader 版本 npm i css-loader@5.0.1 -D
关闭 css-loader 图片打包功能:
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
url: false,
},
},
],
}
3.4.1 安装
npm i url-loader -D
3.4.2 配置
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: [loader: "style-loader",loader: "css-loader" ,
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
require("postcss-preset-env"),
],
},
},
},
],
},
{
test: /\.less$/,
use: ["style-loader", { loader: "css-loader" }, "less-loader"],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: "url-loader",
options: {
name: "img/[name]_[hash:6].[ext]",
limit: 100 * 1024,
},
},
],
},
],
},
};
3.5 Webpack5 打包静态资源 实现 url-loader 效果
不需要下载任何loader webpack 打包相关资源:asset module type
{
test: /\.(png|jpe?g|gif|svg)$/,
type: "asset",
generator: {
filename: "img/[name]_[hash:6][ext]",
},
parser: {
dataUrlCondition: {
maxSize: 100 * 1024,
},
},
},
3.6 加载 iconfont 字体文件
Webpack4 版本:
{
test: /\.(eot|ttf|woff2?)$/,
use: {
loader: "file-loader",
options: {
name: "font/[name]_[hash:6].[ext]",
},
},
}
Webpack5 版本:
{
test: /\.ttf|eot|woff2?$/i,
type: "asset/resource",
generator: {
filename: "font/[name].[hash:6][ext]"
}
}
四、插件
4.1 CleanWebpackPlugin 删除打包文件夹
安装: npm install clean-webpack-plugin -D
配置:
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
...
plugins: [new CleanWebpackPlugin()],
};
4.2 HtmlWebpackPlugin 指定HTML文件模板
安装:npm install html-webpack-plugin -D
配置:
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [
...
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "www.bookbook.cc",
template: "./index.html",
}),
],
};
注:在HTML文件中,可以使用ejs语法读取到传入给HtmlWebpackPlugin 的值。 上边的 title 和 template的值都可以在定义的模板中获取,如下:
<title> <%= htmlWebpackPlugin.options.template %> </title>
4.3 DefinePlugin 定义全局常量
DefinePlugin允许在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装)
使用定义的 全局常量和上述方式一样,都是 ejs <% %> 语法
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
module.exports = {
...
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "www.bookbook.cc",
template: "./index.html",
}),
new DefinePlugin({
BASE_URL: "'./'",
}),
],
};
4.4 CopyWebapckPlugin 复制文件夹到打包目录
实现类似vue 项目打包时的public 文件夹复制 安装:npm i copy-webpack-plugin --save-dev
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
const CopyWebapckPlugin = require("copy-webpack-plugin");
module.exports = {
...
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "webpack示例",
template: "./public/index.html",
}),
new DefinePlugin({
BASE_URL: '"./"',
}),
new CopyWebapckPlugin({
patterns: [
{
from: "./public",
to: "public",
globOptions: {
ignore: ["**/index.html"],
},
},
],
}),
],
};
五、支持 Vue3
安装:
npm i style-loader css-loader vue@next vue-loader@next @vue/compiler-sfc -D
配置:
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
const { DefinePlugin } = require("webpack");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.vue$/i,
use: "vue-loader",
},
],
},
plugins: [
new CleanWebpackPlugin(),
new VueLoaderPlugin(),
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: true,
}),
],
};
六、开发服务器
6.1 watch 选项
webpack给我们提供了watch模式:
- 在该模式下,webpack依赖图中的所有文件,只要有一个发生了更新,那么代码将被重新编译;
- 我们不需要手动去运行 npm run build指令了
如何开启watch呢?两种方式:
- 方式一:在导出的配置中,添加 watch: true;
- 方式二:在启动webpack的命令中,添加 --watch的标识;
在启动脚本中加入:
"build": "webpack --watch"
6.2 devServer
安装:npm i webpack-dev-server -D
创建新启动命令:
"scripts": {
"serve": "webpack serve",
}
注意:你需要先配置 HtmlWebpackPlugin 插件指定HTML模板,不然直接执行该命令会因为没有index.html,导致预览的时候出现 404
devServer其他配置:
module.exports = {
...
devServer: {
host: "localhost",
hot: true,
port: 7070,
open: true,
compress: true,
proxy: {
"/api": {
target: "http://localhost:8888",
pathRewrite: {
"^/api": "",
},
changeOrigin: true,
},
},
}
}
七、resolve 解析设置
常用于配置别名,自动识别扩展名
const path = require("path");
module.exports = {
...
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
extensions: [".mjs", ".js", ".json", ".vue"],
modules: ["node_modules"],
}
};
最后,如果你觉得该文章对你有所帮助的话
请点个赞支持一下 🐷(一个赞都没有,太可怜了)
八、我的 webpack.config.js
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const { DefinePlugin } = require("webpack");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebapckPlugin = require("copy-webpack-plugin");
module.exports = {
mode: "development",
devtool: "source-map",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
extensions: [".mjs", ".js", ".json", ".vue"],
modules: ["node_modules"],
},
devServer: {
host: "localhost",
hot: true,
port: 7070,
open: true,
compress: true,
proxy: {
"/api": {
target: "http://localhost:8888",
pathRewrite: {
"^/api": "",
},
changeOrigin: true,
},
},
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
},
{ loader: "css-loader" },
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
require("postcss-preset-env"),
],
},
},
},
],
},
{
test: /\.less$/,
use: ["style-loader", { loader: "css-loader" }, "less-loader"],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: "url-loader",
options: {
name: "img/[name]_[hash:6].[ext]",
limit: 10 * 1024,
},
},
],
},
{
test: /\.(eot|ttf|woff2?)$/,
use: {
loader: "file-loader",
options: {
name: "font/[name]_[hash:6].[ext]",
},
},
},
{
test: /\.e?js$/i,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env"]],
},
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
title: "webpack示例",
template: "./public/index.html",
}),
new DefinePlugin({
BASE_URL: '"./"',
}),
new CopyWebapckPlugin({
patterns: [
{
from: "./public",
to: "public",
globOptions: {
ignore: ["**/index.html"],
},
},
],
}),
],
}
|