0 前言
最近在工作过程中遇到一个需求,需要将前端项目打包为静态资源并且部署到CDN。这个对于我这个刚入行的前端小菜鸟来说,完全是一脸懵逼,大概只知道这个跟webpack有关。因为项目的基础搭建工作是另一位老鸟搭建的,期间我只会写写业务代码。这次的任务对我来说是个挑战,所以只能硬着头皮上了。
任务完成之后趁着有点闲暇时间,觉得非常有必要学习下webpack的知识。在掘金找到了一篇详细的入门讲解 webpack4.x最详细入门讲解,作者写得非常详细且完整,完全是手摸手教的级别,于是跟着巧了一遍代码,受益匪浅,在此感谢原文作者。但是在时间过程中也难免会遇到版本不一致的导致的问题,在此记录一下,算作是对原文的补充吧。
1 踩坑记录
1.1 执行 webpack src/index.js --output dist/bundle.js 命令时报错 Unknown argument: --output
原因分析:可能跟操作系统有关,使用的终端是 Windows Powershell,使用 git 自带的终端也提示这个错误。
解决方法:把 --optput 改为 -o
1.2 webpack src/index.js -o dist/bundle.js 命令提示 Can't resolve 'src/index.js' in 'E:\02_learning\webpack'
原因分析:可能跟终端读取路径有关
解决方法:把命令中的 src/index.js 改为 ./src/index.js
1.3 构建得到的生成文件夹而不是文件
原因分析:
- ① 没有指定输出文件名;
- ② webpack-cli版本太高。本人在时间过程中使用
yarn add webpack webpack-cli -D命令安装时,webpack 和 webpack-cli 的版本分别如下
毕竟是webpack4的教程,发现问题后改为4的版本,对应的 webpack-cli 改为3.3的版本,如下图
解决方法: - ① 在
webpack.config.js配置文件中配置输出的文件路径和文件名
// webpack.config.js
module.exports = {
entry: __dirname + "/src/index.js", // 入口文件
output: {
path: __dirname + "/dist", //打包后的文件存放的地方
filename: "bundle.js" //打包后输出文件的文件名
}
}
- ② 降低 webpack-cli 版本
1.4 yarn 安装依赖时提示 An unexpected error occurred: "EPERM: operation not permitted, unlink 'XXX'
原因分析:当前的 binding.node 进程正在运行中,必须断开进程才能继续安装当前的依赖。
解决方法:ctrl+c 结束正在进行的进程再执行安装.(参考:yarn add依赖的时候报错)
1.5 使用 clean-webpack-plugin 插件在打包过程中,抛出 TypeError: CleanWebpackPlugin is not a constructor 的错误
原因分析:clean-webpack-plugin 3.0 版本引入模块方式改变。
解决方法:将原来的引用方式
const CleanWebpackPlugin = require('clean-webpack-plugin') // 错误的写法
改为如下方式引用
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 正确的写法
参考:clean-webpack-plugin 3.0以上报错,TypeError: CleanWebpackPlugin is not a constructor
除此之外,webpack-merge 模块的引用也是使用这种方式,否则报同样的错误
// 正确的写法
const { merge } = require("webpack-merge")
// 错误的写法
// const merge = require("webpack-merge")
1.6 使用 postcss-loader 和 autoprefixer 添加css前缀无效
原因分析:未配置 browserslist
解决方法:在 package.json 文件中添加 browserslist,如下
//package.json
{
...
"browserslist": [
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
}
参考:记一次webpack配置postcss-loader下的autoprefixer无效的情况
1.7 使用 mini-css-extract-plugin 插件分离 css 文件
说明:原作者使用的是 extract-text-webpack-plugin 插件,经查阅发现现在 webpack 更推荐使用 mini-css-extract-plugin 插件,故自己照猫画虎实践了一番。
使用方法:
安装模块:
yarn add mini-css-extract-plugin -D // 安装 mini-css-extract-plugin 插件
在 webpack.common.js 文件中进行配置
// webpack.common.js
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// 其他配置省略
...
module: {
rules: [
{
test: /\.css$/, // 匹配以.css结尾的文件
use: [
// 采用对象的形式配置loader
{
loader: MiniCssExtractPlugin.loader, // 使用mini-css-extract-plugin插件提取css
},
{
loader: "style-loader",
},
{
loader: "css-loader",
},
{
loader: "postcss-loader", // 使用postcss-loader。其配置也单独抽离到postcss.config.js文件中
},
],
},
// 其他配置省略
...
],
},
// 使用插件
plugins: [
// 其他配置省略
...
new MiniCssExtractPlugin({
filename: "css/[name].css",
}), // 将css分离到/dist文件夹下独立为css文件
],
};
遇到问题:使用命令 yarn build 时 mini-css-extract-plugin 插件报错 Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js): ReferenceError: document is not defined
原因分析:mini-css-extract-plugin 的 loader 与 stye-loader 冲突。
解决办法:注释掉 stye-loader,如下:
// webpack.common.js
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// 其他配置省略
...
module: {
rules: [
{
test: /\.css$/, // 匹配以.css结尾的文件
use: [
// 采用对象的形式配置loader
{
loader: MiniCssExtractPlugin.loader, // 使用mini-css-extract-plugin插件提取css
},
// {
// loader: "style-loader", // 此loader与mini-css-extract-plugin插件冲突
// },
{
loader: "css-loader",
},
{
loader: "postcss-loader", // 使用postcss-loader。其配置也单独抽离到postcss.config.js文件中
},
],
},
// 其他配置省略
...
],
},
// 使用插件
plugins: [
// 其他配置省略
...
new MiniCssExtractPlugin({
filename: "css/[name].css",
}), // 将css分离到/dist文件夹下独立为css文件
],
};
2 其他
原文作者在项目中使用的是 javascrpt 内置的 path 模块,在表示路径语法是 path.join( __dirname, "/dist"),本人全程使用的是 node.js 中的一个全局变量 __dirname,表示为 __dirname + "/dist"。
3 总结
学到很多,受益匪浅,感谢原文作者大佬。
此文仅为记录个人在实践过程中遇到的问题,仅供参考。源码以提交 github,如有不正确或者不完整还望各位大佬斧正。