webpack5 初始化《JJ》主题 上部
初始化安装
yarn init
yarn add webpack webpack-cli --dev
webpack建议全局安装,省事
yarn global add webpack webpack-cli
如果不适用全局安装,直接在终端运行本项目的webpack需要使用npx
命令
npx webpack -v
还有一个种办法就是在package.json创建快捷npm脚本,这样就不用加npx前缀了
{
"scripts": {
"build": "webpack"
},
}
使用scss
yarn add style-loader css-loader sass sass-loader --dev
webpack.config.js
const path = require('path');
const resolve = function (myPath) {
return path.resolve(__dirname, myPath);
};
module.exports = {
mode: 'development', //模式
//入口
entry: {
index: './src/pages/home/index.js'
},
// 出口
output: {
path: resolve('./dist'), //指定输出目录
filename: '[name]/index.js', //文件名
chunkFilename: '[id].js'
},
//模块-解析器loader
module: {
rules: [
//css
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
// scss
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
]
}
]
}
}
如果你想要打包scss文件,你需要在入口js文件里面引入你的scss文件
import "./index.scss";
webpack在打包的时候就会处理了,但是他的处理方式是将你的js和css打包到一个js文件里,从单页角度看,还是可以的,但是我么普通项目就不需要这样,我们就可以使用一个css压缩的插件。
scss全局变量
yarn add sass-resources-loader --dev
在sass-loader之前配置sass-resources-loader
//模块-解析器loader
module: {
rules: [
// scss
{
test: /\.scss$/,
use: [
'cache-loader',
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: [
resolve("./src/assets/scss/vars.scss"),
resolve("./src/assets/scss/mixins.scss"),
resolve("./src/assets/scss/functions.scss"),
]
}
}
]
},
]
}
css样式抽离-css单独保存
yarn add mini-css-extract-plugin --dev
在webpack3.x的时候用的extract-text-webpack-plugin
,4和5用的这个mini-css-extract-plugin,所以,有兴趣自行百度咯!
webpack.config.js
const path = require('path');
const resolve = function (myPath) {
return path.resolve(__dirname, myPath);
};
//样式抽离
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: 'development', //模式
//入口
entry: {
index: './src/pages/home/index.js'
},
// 出口
output: {
path: resolve('./dist'), //指定输出目录
filename: '[name]/index.js', //文件名
chunkFilename: '[id].js'
},
//模块-解析器loader
module: {
rules: [
//css
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
// scss
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
]
}
]
},
// 插件
plugins: [
new MiniCssExtractPlugin({
filename: '[name]/style.css', //输出的css文件名,默认以入口文件名命名(例如main.css)
chunkFilename: "[id].css", //公共样式??
}),
]
}
这里就有说头了,webpack的解析器loader他是以数组的倒序开始的,也就是,最末尾设置的最开始使用,我们的scss之前的设置顺序是:
['style-loader','css-loader','sass-loader']
那么它的使用顺序就是:sass-loader -> css-loader -> style-loader
而最后执行的style-loader他的作用就是将css打包进js文件里面,所以,如果我想单独提取到css文件,就必须去掉这个解析器,使用MiniCssExtractPlugin.loader
当然单单设置解析器还不行,我们还需要启用这个插件,在plugins插件数组里面,new出这个插件,然后填入配置,具体都有注释,想了解更多可以来npm看下: mini-css-extract-plugin
css自动添加前缀
css有一些hack用法,也有一些样式需要加上浏览器的自定义前缀,那么,最求最新写法的我们,当然可能每个前缀给你记住,所以自动添加前缀是一个很有必要的措施。
yarn add autoprefixer postcss-loader --dev
autoprefixer是postcss的一个插件
postcss本身也是需要配置的,不然无法使用autoprefixer,但postcss解析器只能处理css,所以,一定要写在sass-loader前面,(顺序问题前面已经讲了)
module.exports = {
module: {
rules: [
//css
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
// scss
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
]
}
]
},
}
配置完这个我们还需要创建一个postcss.config.js
文件,这个文件与webpack.config.js
同级。
postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
除了这个还需要创建一个兼容浏览器的配置文件.browserslistrc
,也是同级。
我们可以在vue cli项目上看到这个文件,所以,照抄就行了
.browserslistrc
> 1%
last 2 versions
not dead
然后我们可以尝试打包一些这段css测试一下:
@media (min-resolution: 2dppx) {
.image {
background-image: "";
}
}
打包后应该会编译为:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.image {
background-image: "";
}
}
功能没问题
更强的css处理
yarn add postcss-preset-env --dev
postcss-preset-env可以做到autoprefixer的功能,还能更强,他可以将现代的css转换成浏览器能解析的内容,除了添加浏览器前缀,还能解析16进制的颜色(谷歌f12控制台查看css,部分颜色是16进制了),还能根据目标浏览器或者运行时环境添加所需的polyfill。
总之强就对了,开搞
postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')
]
}
这样完事,你可以在css里面测试一下
@media (min-resolution: 2dppx) {
.image {
background-image: #12321313;
}
}
打包后应该会编译为:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.image {
background-image: rgba(18,50,19,0.07451);
}
}
完美。
处理css中的 @import属性问题
在传统css中使用@import他是一个原生功能,引入另一个css文件,但是,如果你在css中使用@import,被引入的那个文件并不会经过postcss的处理,它属于css语法,所以,能处理到被引入的文件只有: css-loader、style-loader、MiniCssExtractPlugin.loader
style-loader我们弃用了,所以能处理解析器是:css-loader
解决方法:
module.exports = {
module: {
rules: [
//css
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader'
]
},
// scss
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader',
'sass-loader',
]
}
]
},
}
css-loader中importLoaders表示impor引入文件要用哪个已经配置的解析器处理,0表示它自身,1表示往后倒一位,就是postcss-loader
。
如果postcss-loader在后几位,就对应加上
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 3
}
},
'xxxx-loader',
'xxxx-loader',
'postcss-loader',
'sass-loader',
]
}
注意:
css的@import引入并不会按照引入语法的位置引入css。
@import "xxx.css"; //或者 @import url("xxx.css");
使用这种写法,引入的css文件会作用在最开头;
div {
color:#000;
}
@import "color.css";
color.css
div {
color: red;
}
按我们的写法,我们希望的是color.css发挥作用,但是实际情况是这样的:
div {
color: red;
}
div {
color:#000;
}
所以,用的时候需要注意。
css压缩
MiniCssExtractPlugin推荐使用css-minimizer-webpack-plugin
来压缩css
yarn add css-minimizer-webpack-plugin --dev
npm地址:css-minimizer-webpack-plugin
在webpack的优化选项中使用
//css压缩
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
//优化
optimization: {
minimize: true, //开发模式也压缩代码
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: 'advanced', // 需额外安装
},
}),
]
}
}
advanced这个功能用于移除未使用的css,但是需要额外安装一个插件:
yarn add cssnano-preset-advanced --dev
除了advanced模式,还有default和lite模式,具体可以去查查了,能用就行。
注意:如果不开启minimize: true
,那么代码在开发模式就不会压缩,除非你将mode
模式改为生产模式:production
webpack.config.js
module.exports = {
mode: 'production',
}
每次打包前删除dist
由于每次打包,其实是文件的覆盖,如果打包的时候,有一个文件没有了,但是上一次打包存在的,那么就会产生文件残留,所以,我们需要再每次打包的时候,先清理掉dist再重新生成。
yarn add clean-webpack-plugin --dev
webpack.config.js
//清理打包文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// 插件
plugins: [
//清理打包文件
new CleanWebpackPlugin(),
]
}
这样即可。
javascript配置babel
yarn add @babel/core babel-loader @babel/preset-env --dev
webpack.config.js
module.exports = {
module:{
rules:[
// js
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
完成
压缩javascript
babel配置完毕后,我们还需要处理js的压缩,默认webpack5自动安装了TerserPlugin
插件,其他版本则需要手动安装,我们webpack5直接引入并使用即可。
//js压缩
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
//优化
optimization: {
minimize: true, //开发模式也压缩代码
minimizer: [
//js压缩优化
new TerserPlugin({
parallel: true, // 可省略,默认开启并行
terserOptions: {
toplevel: true, // 最高级别,删除无用代码
ie8: true,
safari10: true,
}
})
]
}
}
minimize: true
的理由也是和css一样,开发模式,代码是不会进行压缩处理的,需要配置这个查看效果。
处理LICENSE文件
开启压缩后,会生成xxx.LICENSE.txt
文件,这个文件用于存放注释用的,压缩时会将所有的注释提取到保存成这种文件,如果不想生成,我们可以关闭该功能。
//js压缩
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
//优化
optimization: {
minimize: true, //开发模式也压缩代码
minimizer: [
//js压缩优化
new TerserPlugin({
parallel: true, // 可省略,默认开启并行
terserOptions: {
toplevel: true, // 最高级别,删除无用代码
ie8: true,
safari10: true,
},
extractComments: false, //关闭生成LICENSE文件
})
]
}
}
稍微优化那么一丢丢babel
// js
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/, // 不处理该文件夹下的js文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
}
},
}
/\.m?js$/
官方说可以编辑更少的文件,但是会导致加载到node_modules
目录,所以我们后面exclude黑名单中将一些不需要编译的目录设置了。
路径别名
这个还是很重要的
webpack.config.js
module.exports = {
//解析器
resolve: {
alias: {
'@': resolve('./src')
}
}
}
resolve方法在最上面就定义过了,这里就省略书写了。
代码分割-拆包
- 把多个页面共用的第三方库(比如React,Fastclick)单独打包出一个
vendor.js
- 把多个页面共用的逻辑代码和共用的全局css(比如css-reset,icon字体图标)单独打包出
common.js
和common.css
- 把运行时代码单独提取出来
manifest.js
- 把每个页面自己的业务代码打包出
page1.js
和page1.css
webpack.config.js
module.exports = {
//优化
optimization: {
//拆包
splitChunks: {
chunks: 'async',
cacheGroups: {
// 打包第三方库的文件
vendors: {
name: `vendor`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial',
// minChunks: 2, // 同时引用了2次才打包
},
// 打包业务中公共代码
common: {
name: `common`,
minChunks: 2, // 同时引用了2次才打包
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
runtimeChunk: { name: 'manifest' } // 运行时代码
}
}
实际效果就是:
node_modules中安装的库,在被两次引用后会打包到vendor的文件内;
而多次使用的js代码和css代码会被提取到common中。
剩下的就是各归各的了。
区分下生产和开发模式
做一个简单的效果区分,在开发模式下,我们关闭代码压缩,在生产模式下,我们开启代码压缩和map文件文件生成。
官方示例上有一个很简单的办法,省的安装cross-env
来配置环境变量了,windows的痛。
webpack --mode=development
如果要获取,那么webpack.config.js就必须导出一个方法用于接收参数。
module.exports = (env, argv) => ({
mode: argv.mode || 'development', //模式 development、production
devtool: argv.mode === 'production' ? 'source-map' : 'eval',
})
记得关闭optimization下的minimize属性。
然后我们在package.json
里面配置两个命令
{
"scripts": {
"dev": "webpack --mode=development",
"build": "webpack --mode=production"
},
}
运行dev
则是开发模式
运行build
则为生产模式
watch监听文件
基本上的东西都配置好了,但是每次修改一次文件就要运行一次太累了,我们希望他能自动监听文件的变化,自动打包生成文件。
webpack.config.js
module.exports = (env, argv) => ({
// 监听
watch: argv.mode === 'development', //开发模式监听
//监听的配置
watchOptions: {
aggregateTimeout: 600, //延迟600ms打包
ignored: /node_modules/, //忽略
}
})
ignored可以忽略监听一些内容过多的文件夹,多个就用数组,可以用正则匹配
代码分析
分析有时候还有有必要的,看看自己的文件打包后大小,什么东西占据最大的部分啥的,有利于优化。
yarn add webpack-bundle-analyzer --dev
由于webpack默认在生产模式会开启concatenateModules,导致分析不完整,所以我们还需要在分析模式关闭这个配置,但是我们必须判断运行的命令是否为分析模式,所以,我们还是需要安装cross-env
yarn add cross-env --dev
package.json
"scripts": {
"dev": "webpack --mode=development",
"build": "webpack --mode=production",
"analyzer": "cross-env ANALYZER=true webpack --mode=production"
},
analyzer为分析命令,分析肯定还是要在生产模式下的。
webpack.config.js
//分析
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = (env, argv) => ({
// 插件
plugins: [
//代码分析
(process.env.ANALYZER && new BundleAnalyzerPlugin({
analyzerMode: "static", //生成静态文件
})),
],
//优化
optimization: {
concatenateModules: process.env.ANALYZER ? false : true, //分析模式禁用他,不然分析不全面
}
})
基本就这样。
我们设置生产静态文件,不然默认设置会开启一个http服务,挺烦的,还需要手动关闭,还是生成静态文件方便一些。
yarn remove @babel/plugin-transform-modules-commonjs @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs3
使用cache-loader加速编译
yarn add cache-loader --dev
module.exports = (env, argv) => ({
//模块-解析器loader
module: {
rules: [
//css
{
test: /\.css$/,
use: [
'cache-loader',
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader'
]
},
// scss
{
test: /\.scss$/,
use: [
'cache-loader',
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader',
'sass-loader',
]
},
// js
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/, // 不处理该文件夹下的js文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
cacheDirectory: true, //开启缓存
}
},
}
]
},
});
全局jquery
如果是普通使用jq,只需要安装后import引入即可。
yarn add jquery --dev
使用
import $ from "jquery";
$(function () {
console.log(111);
})
如果要使用插件啥的,可能还需要丢入全局
yarn add expose-loader --dev
然后再webpack.config.js中配置一下
module.exports = (env, argv) => ({
//模块-解析器loader
module: {
rules: [
// jquery
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
},
]
}
})
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据