WebPack的使用及思路
webpack每年升级, 本文基于webpack@4.43.0。
即使版本升级,每部分细节会有变化,本文思路依然有效。
webpack是干什么的
- 转译代码
ES6转为ES5, SCSS转为CSS
- 构建build
- 代码压缩
- 代码分析
安装webpack
- webpack@4
如果webpack升级到了5,本文的思路依然有效
- webpack-dev-server
用于本地预览
查看webpack版本:
npm info webpack
在一个文件夹里引入webpack
mkdir webpack-demo
cd webpack-demo
npm init -y // 创建了package.json
yarn add webpack webpack-cli --dev // 多了一个node_modules目录
如何调用本地安装的webpack
./node_modules/.bin/webpack --version
- 简易写法:
npx webpack
不够稳定,不能使用的话,就用上一种方法
Error: The 'mode' option has not been set
解决方法: Configuration | webpack
webpack配置entry和output
- 设置webpage.config.js
// webpack.config.js
var path = require("path");
module.exports = {
mode: "development", // 或"production"
// 入口
entry: "./src/index.js",
// 出口
output: {
// 转译后的js文件放在dist目录
path: path.resolve(__dirname, "dist"),
// 转译后的js文件,例如:dist/main.8e786759cc25ae130389.js
filename: "[name].[contenthash].js" // filename: "bundle.js"
}
};
webpack插件自动生成HTML
- 修改package.json
"scripts": {
"build": "rm -rf dist; webpack",
}
之后可以通过
yarn build
或者npm run build
构建
- 安装
HtmlWebpackPlugin
npm install --save-dev html-webpack-plugin
改完之后再yarn build
, 发现dist
目录下已经有了index.html
扩展阅读: 利用template生成HTML
webpack引入CSS
- 安装
css-loader
npm install --save-dev css-loader
- 安装
style-loader
npm install --save-dev style-loader
- 配置webpage.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
使用webpack-dev-server
如果你觉得每次build很麻烦,可以使用webpack-dev-server来加快开发: Development | webpack
- Setting mode to development
// webpack.config.js
module.exports = {
mode: 'development',
}
- Using source maps
// webpack.config.js
module.exports = {
devtool: 'inline-source-map',
}
- 安装webpack-dev-server
npm install --save-dev webpack-dev-server
webpack.config.js
module.exports = {
devServer: {
contentBase: './dist',
},
}
package.json
{
"name": "development",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
+ "start": "webpack-dev-server —open",
"build": "webpack"
},
- 配置完成,自己试试吧~
yarn start
使用插件提取CSS文件
- 安装
mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin
- 配置webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader,'css-loader'],
},
],
},
};
- 自己试试
yarn build
此时发现,dist目录下已经有生成的main.css,并且main.css已经被自动引入到index.html中了
- 如何让main.css像main.8e786759cc25ae130389.js一样,中间有个哈希值?
// webpack.config.js
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
}),
],
使用两个webpack config文件(多份webpack config配置)
开发环境(development)和生产环境(production)的webpack配置
development:
yarn start
production:
yarn build
为什么要有development和production两个mode
- 开发环境和生产环境的构建目标是有很大的不同的。
- 在开发环境中,为了便于代码调试以及实现浏览器实时更新,我们需要开启
source map
和localhost server
。 - 在生产环境中,为了实现缓存优化以及改善加载时间,我们的目标转向于打包成更小的
bundle
或chunk
,分离第三方包以及开启更轻量级的source map
以及更优化的资源。 - 因此开发环境和生产环境需要单独配置 webpack。
start开发用,build打包给用户。(development开发用, production给用户用)
如何区分
Q: 上面看了那么多,既然是不同的命令,那能不能设置他们两个用不同的config?如果用不同的config,不就可以自由切换了?
A: 你可真是个小机灵鬼,那我们就试试吧。
- 首先看看webpack有哪些用法:
npx webpack --help
- 修改package.json
更改默认的配置文件,build的时候不使用默认的配置,而使用webpack.config.prod.js这个配置
{
"scripts": {
"start": "webpack-dev-server —open",
"build": "rm -rf dist && webpack --config webpack.config.prod.js",
},
注意将webpack.config.prod.js中的mode改为production
多份webpack config配置
Q: 我们现在使用了两个配置文件,分别是webpack.config.js用于开发模式,webpack.config.prod.js用于生产模式, 对吧?
A: 对。
Q: 那我觉得你有点傻,因为这两个文件基本都相同啊,你就不能简化一下?
A: 彳亍口巴,请继续看,我把它们拆成了三个文件
webpack.config.base.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].[contenthash].js", // 默认[name] 为 main
},
plugins: [
new HtmlWebpackPlugin({
title: "My App",
template: "src/assets/index.html",
}),
],
};
webpack.config.js
development的config
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const base = require("./webpack.config.base.js");
module.exports = {
...base, // 把base的所有属性搞过来
devtool: "inline-source-map",
devServer: {
contentBase: "./dist",
},
mode: "development",
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
webpack.config.prod.js
production的config
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const base = require("./webpack.config.base.js");
module.exports = {
...base,
mode: "production",
plugins: [
...base.plugins,
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].[hash].css",
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
这样一来,利用继承,就清爽多了
扩展阅读: GitHub - survivejs/webpack-merge: Merge designed for Webpack
webpack loader vs webpack plugin
- loader是加载器,用来加载某些资源文件。比如说,babel-loader是用来加载高级的JS,把它变成浏览器支持的JS。css-loader和style-loader是用来加载css的,把它变成页面中的style标签。
- plugin是插件,用来扩展webpack的功能。比如html-webpack-plugin是用来生成HTML文件的,mini-css-extract-plugin则是用来抽取css的代码,把它合并成一个css文件的。
引入SCSS
- 安装
sass-loader
npm install sass-loader sass webpack —save-dev
- 修改webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},
};
注意,node-sass已经过时了,请使用 dart-sass(sass)
yarn start
试试
扩展阅读 GitHub - sass/dart-sass: The reference implementation of Sass, written in Dart.
引入LESS
- 安装
less loader
npm install less-loader --save-dev
- 修改webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/,
loader: 'less-loader', // compiles Less to CSS
},
],
},
};
Module parse failed: Unexpected token
解决办法
修改webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.less$/,
loader: ['style-loader', 'css-loader', 'less-loader'],
},
],
},
};
这一步的目的是: 将less转成css,将css转成JS,再将JS转成style标签
Q:
Error: Cannot find module 'less’
解决办法?A:
yarn add less --dev
装一下less不就好了
yarn start
试试
引入Stylus
- 安装
less loader
npm install stylus-loader stylus --save-dev
- 修改webpack.config.js
module: {
loaders: [{
test: /\.styl$/,
loader: 'css-loader!stylus-loader?paths=node_modules/bootstrap-stylus/stylus/'
}]
}
实际上这是一种过时的语法,正确的写法:
module: {
loaders: [{
test: /\.styl$/,
loader: ['style-loader', 'css-loader', 'stylus-loader'],
}]
}
yarn start
试试
使用file-loader引入图片
- 安装
file-loader
$ npm install file-loader --save-dev
- 修改webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader', // 把文件变成文件路径
},
],
},
],
},
};
yarn start
试试
webpack import() 懒加载
所谓懒加载,顾名思义,该加载的时候不加载,等不得不加载的时候再加载
Q: 如何实现懒加载?
A: 用import()去加载文件,然后我会得到一个promise,promise的前面写成功之后做什么,后面写失败之后做什么。
- 例子:
index.js
const button = document.createElement("button");
button.innerHTML = "lazy load";
button.onclick = () => {
const promise = import("./lazy");
promise.then(
(module) => {
const fn = module.default;
fn();
},
() => {
console.log("Error in loading module");
}
);
};
lazy.js
export default function lazy() {
console.log("I am a lazy load module");
}
webpack一键部署到github
原始的方法–使用master分支
分两步,第一步是本地打包,第二部是上传到github
- build一下
yarn build
- 可以本地使用http-server测试一下
cd dist/
hs -c-1
没有http server的话,可以使用
yarn add http-server
安装一下
- GitHub新建目录,然后上传到GitHub
git remote add origin URL
git push -u origin master
- 进入项目的Settings > GitHub Pages,Source改为项目所在的分支。
此时项目发布在 URL/dist/index.html
使用gh-pages分支
Q: 我不想用dist,我不希望用户看到
/dist/index.html
这么奇怪的路径,怎么办?A: 彳亍口巴,那我们使用新分支。
- 新建分支
git branch gh-pages
- 进入这个分支
git checkout gh-pages
- 删除除了
dist
,node_modules
,.gitignore
之外的所有文件 - 把
dist
目录下的所有文件拷到当前目录并删除dist
mv dist/* ./
rm -rf dist
git add
,git commit
,git push
素质三连
这样就可以平时在master分支开发,然后在gh-pages分支发布了
- 进入项目的Settings > GitHub Pages,Source改为gh-pages分支。
- 稍等GitHub一会,就可以预览啦~
使用脚本简化
每次这么做也太累了⑧,使用脚本简化一下吧
- 切回master分支
git checkout master
- 新建deploy.sh, 写入:
yarn build &&
git checkout gh-pages &&
rm -rf *.html *.js *.css *.png &&
mv dist/* ./ &&
rm -rf dist;
git add . &&
git commit -m ‘update’ &&
git push &&
git checkout - # '-'代表之前的分支
这样以后就可以通过
sh deploy.sh
完成之前的所有功能了
经验:先提交再部署(deploy),是一个好习惯