一、Webpack简介
1.1 webpack是什么
webpack 是一种前端资源构建工具,一个静态模块打包器。
在webpack看来,前端的所有资源文件(js | json | css | img | less …)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源。
1.2 webpack核心概念
Entry
入口:指示webpack以哪个文件为入口起点开始打包,分析构建内部依赖图。
Output
输出:指示webpack打包后的资源输出到哪里去,以及如何命名。
Loader
Loader: 让webpack能够处理非JS的文件,如样式文件、图片文件等(webpack自身只能理解js和json文件)。
Pulgins
Pulgins:可以用于执行范围更广的任务,包括打包优化、资源管理
注入环境变量。
Mode
Mode:告知webpack使用相应模式的内置优化(默认值为:production)。
二、Webpack初体验
2.1初始化配置
- 初始化pageage.json: npm init
- 下载安装webpack:
全局安装:npm i webpack webpack-cli -g
本地安装:npm i webpack webpack-cli -D
2.2编译打包
创建src下的index.js等文件后,在命令行中编译打包。
运行指令:
- 开发环境:webpack ./src/index.js -o ./build/build.js --mode=development
(webpack会以.src/index.js 为入口文件开始打包,打包输出到./build/build.js,整体打包环境是开发环境) - 生产环境:webpack ./src/index.js -o ./build/build.js --mode=production
(webpack会以.src/index.js 为入口文件开始打包,打包输出到./build/build.js,整体打包环境是生产环境)
结论:
- 生产环境和开发环境将es6模块化编译成浏览器能识别的模块化。
- 生产环境比开发环境多一个压缩js代码。
三、Webpack开发环境的基本配置
webpack.config.js 是webpack的配置文件。
作用:指示 webpack 干哪些活(当你运行webpack指令时,会加载里面的配置。
所有的构建工具都是基于nodejs平台运行的 模块化默认采用commonjs。
下面是一个简单的开发环境webpack.config.js配置文件
开发环境配置考虑:
- 打包样式资源
- 打包html资源
- 打包图片资源
- 打包其他资源
- devServer
// resolve用来拼接绝对路径的方法
const {resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
// 入口文件
entry:"./src/index.js",
// 输出文件
output:{
// 输出文件名
filename:'build.js',
// 输出路径
// __dirname 是nodejs的变量,代表当前文件的目录绝对路径
path:resolve(__dirname,'build')
},
// loader的配置
// 1、下载 2、使用(配置loader)
module:{
rules:[
// 详细loader配置
// 不同文件必须配置不同loader配置
{
// css
// 匹配文件
test:/\.css$/,
// 使用那些loader进行处理
use:[
// use数组中loader执行顺序:从右到左,从下到上
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
// 讲css文件变成commonjs模块加载到js中,里面内容是样式字符串
'css-loader'
]
},{
// less
test:/\.less$/,
// 多个loader处理使用use
use:[
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
// 讲css文件变成commonjs模块加载到js中,里面内容是样式字符串
'css-loader',
// 讲less文件编译成css文件
// 需要下载less和less-loader
'less-loader'
]
},{
// 处理图片资源(默认处理不了html中的img图片)
test:/\.(jpg|jpeg|png|gif)$/,
// 一个loader处理使用loader
// 下载url-loader file-loader
loader:'url-loader',
// 图片大小小于8kb,就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
options:{
limit:8 * 1024,
// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
// 解析时会出现的问题:[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule:false,
// 给图片重命名
// [hash:10]取图片的hash的前10位 [ext]取文件原来扩展名
name:'[hash:10].[ext]',
outputPath: 'imgs'
}
},{
test:/\.html$/,
// 处理html文件中的img图片(负责引入img, 从而能被url-loade进行处理)
loader:'html-loader',
options:{
esModule:false
}
},{
// 打包其他资源
// exclude排除其他资源
exclude:/\.(css|js|html|less|json|jpg|jpeg|png|gif)$/,
loader: 'file-loader',
options:{
name:'[hash:10].[ext]',
outputPath: 'other'
}
}
]
},
// plugins的配置
// 1、下载 2、引入 3、使用
plugins:[
// html-webpack-plugin (new调用)
// 功能:默认创建空的HTML,自动引入打包输出的所有资源(js/css)
new HtmlWebpackPlugin({
// 复制 './src/index.html' 文件,自动引入打包输出的所有资源(js/css)
template:'./src/index.html'
})
],
// 模式
mode:'development',
// 开发服务器 devServer:自动化 不用每次修改后输入 webpack命令 打包(自动编译,自动打开浏览器,自动刷新浏览器...)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令:npx(本地) webpack-dev-server || npx webpack serve
devServer:{
// 项目构建后路径
contentBase: resolve(__dirname,'build'),
// 启动gzip压缩
compress: true,
// 端口号
port: 3000,
// 自动打开浏览器
open: true
}
}
四、 Webpack生产环境的基本配置
生产环境配置考虑:
- 提取css成单独文件
- css兼容处理
- js语法检查
- js兼容性处理
- js压缩
- html压缩
const {resolve} = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 设置nodejs环境变量 决定使用browserslist的哪个环境
// process.env.NODE_ENV = 'development'
// 复用loader
const commonCssLoader = [
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
// 'style-loader',
// 这个loader取代style-loader,作用:提取js中的css成单独文件通过link加载
MiniCssExtractPlugin.loader,
// 讲css文件变成commonjs模块加载到js中,里面内容是样式字符串
// 问题:1、js文件体积会很大,2、需要先加载js在动态创建style标签,样式渲染速度慢,会出现闪屏现象
// 解决:用MiniCssExtractPlugin.loader代替style-loader
'css-loader',
/**
* css兼容性处理:postcss => 安装 postcss-loader postcss-preset-env
* postcss-preset-env插件帮postcss找到page.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
* package.json中定义browserslist
"browserslist":{
"development":[
开发环境 => 设置node环境变量: process.env.NODE_ENV = 'development'
"last 1 chrom version", 兼容最近的版本
"last 1 firefox version",
"last 1 safari version"
],
"production":[ 满足绝大多数浏览器兼容
生产环境 (默认生产环境)
">0.2%", 大于99.8%的浏览器
"not dead",
"not op_mini all"
]
}
*/
{
loader: 'postcss-loader',
options: {
postcssOptions:{
plugins: [
// postcss的插件
require('postcss-preset-env')
]
}
}
}
]
module.exports = {
entry:'./src/js/index.js',
output:{
filename:'js/build.js',
path:resolve(__dirname, "build")
},
module:{
rules:[
{
test:/\.css$/,
use:[...commonCssLoader]
},
{
test:/\.less/,
use:[
...commonCssLoader,
'less-loader'
],
},
/**
* 语法检查:下载 eslint-loader eslint
* 注意:只检查自己的源代码,第三方库是不用检查的
* 设置检查规则:
* package.json中 eslintConfig 中设置
* "eslintConfig":{
"extends": "airbnb-base" //继承Airbnb的风格规范
}
* aribnb(js风格库) => 下载 eslint-config-airbnb-base eslint-plugin-import
*/
// 正常来讲,一个文件只能被一个loader处理
// 当一个文件要被多个loader处理,name一定要指定loader执行的先后顺序
// 先执行eslint-loader在执行babel-loader
{
test:/\.js$/,
exclude:/node_modules/,
// 优先执行
enforce: 'pre',
loader:'eslint-loader',
options:{
// 自动修复eslint错误
fix: true
}
},
/**
* js兼容性处理:下载 babel-loader @babel/core @babel/preset-env
* 1、基本js兼容性处理 => @babel/preset-env 解决:使用babel/polyfill
* 问题:只能转换基本语法,如promise等高级语法不能转换
* 2、全部js兼容性处理 => 下载 @babel/polyfill(不需配置 直接在index.js引入import '@babel/polyfill')
* 问题:只要解决部分兼容性问题,但是@babel/polyfill将所有兼容性代码全部引入,体积过大
* 3、按需加载兼容性处理 => 下载core-js
*/
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
options:{
// 预设:指示babel做怎样的兼容性处理
presets:[
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns:'usage',
// 指定core-js版本
corejs:{
version:2
},
// 指定兼容性做到那个版本浏览器
targets:{
chrome:'60',
firefox:'60',
ie:'9',
safari:'10',
edge:'17'
}
}
]
]
}
},
{
// 处理图片资源(默认处理不了html中的img图片)
test: /\.(jpg|jpeg|png|gif)$/,
// 一个loader处理使用loader
// 下载url-loader file-loader
loader: 'url-loader',
// 图片大小小于8kb,就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
options: {
limit: 8 * 1024,
// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
// 解析时会出现的问题:[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule: false,
// 给图片重命名
// [hash:10]取图片的hash的前10位 [ext]取文件原来扩展名
name: '[hash:10].[ext]',
outputPath: 'imgs'
}
}, {
test: /\.html$/,
// 处理html文件中的img图片(负责引入img, 从而能被url-loade进行处理)
loader: 'html-loader',
options:{
esModule:false
}
}, {
// 打包其他资源
// exclude排除其他资源
exclude: /\.(css|js|html|less|json|jpg|jpeg|png|gif)$/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'other'
}
}
]
},
plugins:[
new HTMLWebpackPlugin({
template:'./src/index.html',
// 压缩html代码
minify:{
// 移出空格
collapseWhitespace:true,
// 移出注释
removeComments:true
}
}),
new MiniCssExtractPlugin({
// 对输出的css文件重命名
filename:'css/build.css'
})
],
// 生产环境下自动压缩js代码
mode:'production'
}