webpack5的基本用法
webpack的基本使用
webpack 本身功能有限:
- 开发模式: 仅能编译JS中的
ES Module
语法 - 生产模式: 能编译
ES Module
语法, 还能压缩JS代码
添加实例文件
npm init -y
src/main.js // 引用下面export的函数
src/js/add.js // export 一个 add
src/js/count.js // export 一个 count
public/index.html // 引用打包后的js文件
下载依赖
npm i webpack webpack-cli -D
使用 npx 命令, npx 可以将 node_modules 里面的 .bin 临时 添加为环境变量, 这样就可以访问环境变量里面的应用程序
npx webpack ./src/main.js --mode=development
// 开发环境
npx webpack ./src/main.js --mode=production
// 生产环境
显示: webpack 5.73.0 compiled successfully in 116 ms 编译成功
webpack的初体验
webpack的5大核心概念
- entry (入口), 指示webpack从哪个文件开始打包
- output(输出) 指示打包文件输出到哪里去,如何命名
- loader(加载器) webpack本身只能处理js,json,其他资源需要借助loader
- plugins(插件), 拓展webpack的功能
- mode(模式) 开发模式(development), 生产模式: production
添加webpack的配置文件, 在 根目录下, 固定名称 webpack.config.js
const path = require('path')
module.exports = {
// 入口
entry: './src/main.js', // 相对路径
// 输出
output: {
path: path.resolve(__dirname, 'dist'), // 使用绝对路径
filename: 'main.js'
},
// 加载器
module: {
rules: [
// loader的配置
]
},
// 插件
plugins: [
// 插件配置
],
// 模式
mode: 'development'
}
运行指令打包
npx webpack
// 不用像下面添加参数了, 会自动去找配置文件
//npx webpack ./src/main.js --mode=development
// 也可以添加, 如果添加了, 就会按添加的内容来
开发模式下的配置
- 编译代码, 使浏览器能识别运行,有样式,字体图标, 图片,html等.需要加载配置来处理这些资源
- 代码质量检查, 树立代码规范
处理css文件
npm i style-loader css-loader -D
{
test: /\.css$/, // 只检测css文件
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader' // 将css资源编译成commonjs的模块到js中
]
}
// 运行结果是: 在head标签里面有动态创建一个style标签,里面有引入的css文件
处理less文件
npm i less less-loader -D
{
test: /\.less$/, // 只检测less文件
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'less-loader', // 将 less编译成css
]
}
处理sass文件
npm i sass sass-loader -D
{
test: /\.s[ac]ss$/, // 检测scss或sass
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'sass-loader', // 将 scssss编译成css
]
}
图片处理
// 不需要下载file-loader, url-loader, webpack5内置了
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
// 小于10kb转base64
// 优点: 请求减少, 缺点: 体积变大
maxSize: 10 * 1024, // 10 kb
}
}
}
// 优化点: 小于10kb的图片转化成base64
自动清空上次的打包资源
output: {
path: path.resolve(__dirname, 'dist'), // 使用绝对路径
filename: 'static/js/main.js',
// 自动清空上次打包的内容, 在进行打包
clean: true,
},
修改输出目录
// js文件
output: {
path: path.resolve(__dirname, 'dist'), // 使用绝对路径
// 添加上前缀目录
filename: 'static/js/main.js',
// 自动清空上次打包的内容, 在进行打包
clean: true,
},
// 图片资源
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
// 小于10kb转base64
// 优点: 请求减少, 缺点: 体积变大
maxSize: 15 * 1024, // 10 kb
}
},
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/images/[hash:10][ext][query]'
}
}
处理其他资源: 如: 字体图标
阿里图标库里面下载一个压缩包, 解压, 复制里面的iconfont.css和ttf, woff, woff2文件到项目对应的位置,注意修改相对引用的位置和在main.js里面引入.
配置如下
{
test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
type: 'asset/resource', // 会原封不动的输出
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/media/[hash:10][ext][query]'
}
}
eslint的配置
新建 .eslintrc.js文件
parserOptions: {} // 解析选项
rule具体规则:
-
off 或 0 : 关闭规则
-
warn 或 1 : 开启规则, warn触发, 程序不会退出
-
error 或 2: 开启规则, error级别的错误, error触发, 程序退出
extend 继承规则
使用exlint eslint在webpack4的时候是个loader, webpack5的时候是个plugin
npm i eslint eslint-webpack-plugin -D
注意这里的node版本, 低了会报一些莫名其妙的错, 之前用的是10.16, 不行.建议升级到最新的稳定版
-
新建 .eslintrc.js 文件
module.exports = { // 继承eslint规则 extends: ["eslint:recommended"], // 环境 "env": { "node": true, // 启用node的全局变量 "browser": true, // 启用浏览器的全局变量 }, "parserOptions": { "ecmaVersion": 6, // es6 "sourceType": "module", // es module }, "rules": { "no-var": 2 // 不能使用var } }
-
在plugins里面添加配置
const ESLintPlugin = require('eslint-webpack-plugin'); // 插件 plugins: [ // 插件配置 // eslint的配置 new ESLintPlugin({ // 检测哪些文件 context: path.resolve(__dirname, 'src') }), ],
-
如果本地有eslint插件, 会自动检查本地的所有文件, 但是不需要检测dist目录, 所以需要新建一个 .eslintignore 文件
dist // 不检测dist
babel的用法, 是一个 loader
将es6语法编译成向后兼容的js语法
配置文件名称: babel.config.js
presets预设: 一组babel插件, 拓展babel功能
- @babel/preset-env : 一个只能预设, 允许使用最新的javascript
- 其他, 用的少, 略
npm i -D babel-loader @babel/core @babel/preset-env
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules里面的js文件
loader: 'babel-loader',
// options: {
// presets: ["@babel/preset-env"]
// }
}
新建一个 babel.config.js文件, 也可以直接在上面写, 不过单独文件拓展性更好
// babel.config.js
module.exports = {
// 只能预设, 可以编译es6语法
presets: ['@babel/preset-env']
}
处理html文件 html-webpack-plugin
通过插件自动引入打包的文件
npm i -D html-webpack-plugin
// 引入
const HTMLWebpackPlugin = require('html-webpack-plugin')
// 使用, 注意添加模板
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "public/index.html")
})
开发服务器
npm i webpack-dev-server -D
配置
// 和entry 同级目录
// 开发服务器. 不会输出资源, 在内存中运行
devServer: {
host: 'localhost', // 服务器域名
port: '3000', // 端口
open: true // 自动打开浏览器
},
运行
npx webpack serve
生产环境和开发环境的分离
根目录新建config文件夹, 将原来的webpack.config.js文件丢进入, copy一份, 分别命名为: webpack.dev.js webpack.prod.js
里面改动如下
// 开发环境: webpack.dev.js
// 绝对路径改变, 不需要输出
const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 入口
entry: './src/main.js', // 相对路径 运行的时候还是在根目录下运行, 不用改
// 输出
output: {
// path: path.resolve(__dirname, '../dist'), // 使用绝对路径
path: undefined, // 开发模式没有输出
filename: 'static/js/main.js',
// 自动清空上次打包的内容, 在进行打包
// clean: true,
},
// 加载器
module: {
rules: [
// loader的配置
{
test: /\.css$/, // 只检测css文件
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader' // 将css资源编译成commonjs的模块到js中
]
},
{
test: /\.less$/, // 只检测less文件
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'less-loader', // 将 less编译成css
]
},
{
test: /\.s[ac]ss$/, // 检测scss或sass
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'sass-loader', // 将 scssss编译成css
]
},
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset', // 这个会转base64
parser: {
dataUrlCondition: {
// 小于10kb转base64
// 优点: 请求减少, 缺点: 体积变大
maxSize: 15 * 1024, // 10 kb
}
},
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/images/[hash:10][ext][query]'
}
},
{
test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
type: 'asset/resource', // 会原封不动的输出
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/media/[hash:10][ext][query]'
}
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules里面的js文件
loader: 'babel-loader',
// options: {
// presets: ["@babel/preset-env"]
// }
}
]
},
// 插件
plugins: [
// 插件配置
// eslint的配置
new ESLintPlugin({
// 检测哪些文件
context: path.resolve(__dirname, '../src')
}),
// html资源
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "../public/index.html")
})
],
// 开发服务器. 不会输出资源, 在内存中运行
devServer: {
host: 'localhost', // 服务器域名
port: '3000', // 端口
open: true // 自动打开浏览器
},
// 模式
mode: 'development'
}
// webpack.prod.js 生产环境
// 绝对路径改变, 不需要开发服务器
const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 入口
entry: './src/main.js', // 相对路径
// 输出
output: {
path: path.resolve(__dirname, '../dist'), // 使用绝对路径
filename: 'static/js/main.js',
// 自动清空上次打包的内容, 在进行打包
clean: true,
},
// 加载器
module: {
rules: [
// loader的配置
{
test: /\.css$/, // 只检测css文件
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader' // 将css资源编译成commonjs的模块到js中
]
},
{
test: /\.less$/, // 只检测less文件
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'less-loader', // 将 less编译成css
]
},
{
test: /\.s[ac]ss$/, // 检测scss或sass
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
'css-loader', // 将css资源编译成commonjs的模块到js中
'sass-loader', // 将 scssss编译成css
]
},
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset', // 这个会转base64
parser: {
dataUrlCondition: {
// 小于10kb转base64
// 优点: 请求减少, 缺点: 体积变大
maxSize: 15 * 1024, // 10 kb
}
},
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/images/[hash:10][ext][query]'
}
},
{
test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
type: 'asset/resource', // 会原封不动的输出
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/media/[hash:10][ext][query]'
}
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules里面的js文件
loader: 'babel-loader',
// options: {
// presets: ["@babel/preset-env"]
// }
}
]
},
// 插件
plugins: [
// 插件配置
// eslint的配置
new ESLintPlugin({
// 检测哪些文件
context: path.resolve(__dirname, '../src')
}),
// html资源
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "../public/index.html")
})
],
// 模式
mode: 'production'
}
开发环境的命令:
npx webpack serve --config ./config/webpack.dev.js
生产环境的命令:
npx webpack --config ./config/webpack.prod.js
在package.json中添加命令:
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
},
最后:
开发环境: npm start
生产环境: npm run build
下面时生产模式
Css处理
上面的处理之后, css目前会被打包到js文件中, 当js加载时, 会创建一个style标签来生成样式, 这样对于网站来说, 会出现闪屏现象, 用户体验不好
应该时单独的css文件, 通过link标签去加载性能才好
npm i mini-css-extract-plugin -D
用法:
-
下载 npm i mini-css-extract-plugin -D
-
引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
-
注册
// 处理css new MiniCssExtractPlugin({ filename: "static/css/main.css" })
-
使用
// 将style-laoder改成 MiniCssExtractPlugin.loader { test: /\.css$/, // 只检测css文件 use: [ // 执行顺序: 从右到左, 从上到下 // 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效 不需要了, 提取css成单独文件 MiniCssExtractPlugin.loader, 'css-loader' // 将css资源编译成commonjs的模块到js中 ] }, { test: /\.less$/, // 只检测less文件 // use 可以使用多个loader, loader只能使用一个laoder use: [ // 执行顺序: 从右到左, 从上到下 // 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效 MiniCssExtractPlugin.loader, 'css-loader', // 将css资源编译成commonjs的模块到js中 'less-loader', // 将 less编译成css ] }, { test: /\.s[ac]ss$/, // 检测scss或sass // use 可以使用多个loader, loader只能使用一个laoder use: [ // 执行顺序: 从右到左, 从上到下 // 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效 MiniCssExtractPlugin.loader, 'css-loader', // 将css资源编译成commonjs的模块到js中 'sass-loader', // 将 scssss编译成css ] },
-
结果: 重新打包之后, css时通过link引入的 ok
css兼容性问题
下载:
npm i postcss-loader postcss postcss-preset-env -D
需要postcss-loader, postcss-loader依赖postcss, postcss-preset-env是智能预设,解决样式问题
使用
// 在cssloader后面, less或scss前面使用
{
test: /\.css$/, // 只检测css文件
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效 不需要了, 提取css成单独文件
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, less前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
}
]
},
{
test: /\.less$/, // 只检测less文件
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, less前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
},
'less-loader', // 将 less编译成css
]
},
{
test: /\.s[ac]ss$/, // 检测scss或sass
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, scss前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
},
'sass-loader', // 将 scssss编译成css
]
},
在package.json中定义需要兼容的浏览器范围
"browserslist": [
"last 2 version",
"> 1%",
"not dead"
]
最后打包测试就行了
目前为止的package.json和webpack.prod.js里面的文件
// paceage.json
{
"name": "webapck",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"eslint": "^8.19.0",
"eslint-webpack-plugin": "^3.2.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"mini-css-extract-plugin": "^2.6.1",
"postcss": "^8.4.14",
"postcss-loader": "^7.0.1",
"postcss-preset-env": "^7.7.2",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
"style-loader": "^3.3.1",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
},
"browserslist": [
"last 2 version",
"> 1%",
"not dead"
]
}
// webpack.prod.js
const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// 入口
entry: './src/main.js', // 相对路径
// 输出
output: {
path: path.resolve(__dirname, '../dist'), // 使用绝对路径
filename: 'static/js/main.js',
// 自动清空上次打包的内容, 在进行打包
clean: true,
},
// 加载器
module: {
rules: [
// loader的配置
{
test: /\.css$/, // 只检测css文件
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效 不需要了, 提取css成单独文件
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, less前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
}
]
},
{
test: /\.less$/, // 只检测less文件
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, less前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
},
'less-loader', // 将 less编译成css
]
},
{
test: /\.s[ac]ss$/, // 检测scss或sass
// use 可以使用多个loader, loader只能使用一个laoder
use: [
// 执行顺序: 从右到左, 从上到下
// 'style-loader', // 将js中的css通过创建style标签的方式添加到html文件中生效
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, scss前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
},
'sass-loader', // 将 scssss编译成css
]
},
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset', // 这个会转base64
parser: {
dataUrlCondition: {
// 小于10kb转base64
// 优点: 请求减少, 缺点: 体积变大
maxSize: 15 * 1024, // 10 kb
}
},
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/images/[hash:10][ext][query]'
}
},
{
test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
type: 'asset/resource', // 会原封不动的输出
generator: {
// 输出图片名称, hash 更具文件内容生成的hash值 :10 取前10位, ext: 文件的后缀 query 查询
filename: 'static/media/[hash:10][ext][query]'
}
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules里面的js文件
loader: 'babel-loader',
// options: {
// presets: ["@babel/preset-env"]
// }
}
]
},
// 插件
plugins: [
// 插件配置
// eslint的配置
new ESLintPlugin({
// 检测哪些文件
context: path.resolve(__dirname, '../src')
}),
// html资源
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "../public/index.html")
}),
// 处理css
new MiniCssExtractPlugin({
filename: "static/css/main.css"
})
],
// 模式
mode: 'production'
}
封装公共代码, 简化配置
// 封装公共的函数
function getCommonLoader(loader) {
return [
MiniCssExtractPlugin.loader,
'css-loader', // 将css资源编译成commonjs的模块到js中
{ // 放在css后面, less前面
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'] // 能解决大多数上市兼容性问题
}
}
},
loader
].filter(Boolean)
// 可能没有自定义的loader, 通过filter可以过滤掉
}
使用
{
test: /\.css$/, // 只检测css文件
use: getCommonLoader()
},
{
test: /\.less$/, // 只检测less文件
use: getCommonLoader('less-loader')
},
{
test: /\.s[ac]ss$/, // 检测scss或sass
use: getCommonLoader('sass-loader')
},
css压缩, html和css生产模式下会自动压缩, 不需要配置
下载
npm i css-minimizer-webpack-plugin -D
使用, 可以直接在插件里面new一下就行了
// 处理css
new MiniCssExtractPlugin({
filename: "static/css/main.css"
}),
// 压缩css
new cssMinimizerPlugin()