目录
1.13.3、import 动态导入实现代码分割 ( webpackChunkName )
目标
- 安装 webpack 打包工具到本机
- 熟知 webpack 的核心配置
- 配置好开发环境 devServer
- 配置好相关的 loader 和 plugin
一、webpack
官网:webpack
1.1、webpack 是什么
webpack 是一种前端资源构建工具,一个静态模块 打包器 , 在 webpack 看来,前端的所有资源文件( js / json / css / image / less / sass ... ) 都会作为模块处理 。它将根据模块的 依赖关系 进行静态分析,打包生成对应的静态资源。webpack 可以解决当前 web 开发中所面临的困境,webpack 提供了:
- 友好的 模块化支持
- 代码压缩 混淆
- 处理 js / css 兼容问题
- 性能优化( 模块删减 )
注:webpack 默认只能针对于 js 来进行打包处理
目前绝大多数企业中的前端项目,都是基于 webpack 进行打包构建的 ( vue / react ) 。
从 v4.0.0 开始,webpack 可以不用再引入一个配置文件来打包项目,然而,它仍然有着高度可配置性,可以很好满足你的需求。
默认配置文件: webpack.config.js 或 webpackfile.js
1.2、webpack 五个核心配置
webpack 中文文档(@印记中文) https://docschina.org/
- entry 入口
字符串,数组,对象
本项目应该使用哪个模块,来作为构建其内部依赖图的开始(指定打包入口文件)
- output 输出
对象
在哪里输出它所创建的 bundle,以及如何命名这些文件,默认值为 ./dist
- mode 模式
字符串
通过选择 development ( 开发 ) 或 production ( 生产 ) 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化
- loader 加载器 ( modules )
对象,里面写数组
loader 让 webpack 能够去处理那些非 js 文件 ( webpack 自身只理解 js )
- plugins 插件
数组
插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
1.3、安装 webpack
安装方式 2 种
- 全局安装(不推荐)
npm i -g webpack@4 webpack-cli@3
- 局部安装 (推荐)
webpack 是运行在 node 环境中的,Node >= 8.10 和 npm >= 5.6
npm init -y
npm i -D webpack@4 webpack-cli@3
{
webpack 打包使用的 核心代码
webpack-cli 打包使用时的 命令
}
![]()
安装好后可以通过先前提及过的 npx 命令来检查 webpack 的版本以确定是否安装成功:
npx webpack --version
在 package.json 文件中配置 webpack 运行脚本命令
"scripts": {
"build": "webpack --version"
},
1.4、webpack 基本使用
webpack 默认情况下,会在 ./src 目录下面去找 index.js 入口文件,默认是不需要任何的webpack 配置。
默认入口 src / index.js
默认出口 dist / main.js
在项目根目录下面创建一个 webpack.config.js 文件,此文件是 webpack 的默认配置文件名称,后续就可以在此目录下面对 webpack 进行运行打包配置。
const path = require('path')
# 删除打包的 dist 目录
npm i -D clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// 打包模式 development | production
mode: 'development',
// 项目入口
entry: './src/index.js',
// entry:{'main': './src/main.js'} // 多入口
// entry:['./src/index.js', './src/main.js'] // 合并
// 项目出口
output: {
// 路径一定要用绝对路径
path: path.resolve('dist'),
// [name]默认的名称为 main
// [hash]随机生成 21 位字符串
filename: 'js/[name].js'
},
plugins:[
new CleanWebpackPlugin()
]
}
1.5、配置访问入口模板文件
在项目根目录下面创建一个 public 目录,并在此目录中创建一个 index.html 文件,使用 webpack的 html-webpack-plugin 插件,可以将此文件用于项目 web 入口文件模块
# 安装
npm i -D html-webpack-plugin@4
# 引入
const HtmlWebpackPlugin = require('html-webpack-plugin')
# 使用 webpack.config.js
plugins: [
new HtmlWebpackPlugin({
template: path.resolve('public/index.html'),
})
]
1.6、devServer 创建
我们已经可以使用打包工具去将写好的代码进行打包了,但是在操作的过程中大家可能会发现有一个比较麻烦的地方:修改一次代码就得重新打包一次,那么有没有在开发阶段,编写代码后自动进行编译看效果并且最好还能提供 web 服务的功能呢? 答案是有的,它就是 webpack-dev-server 自动化打包工具。
# 安装 webpack-dev-server
npm i -D webpack-dev-server@3
# 配置 node 环境 web 环境
devServer: {
// 端口号
port: 8080,
// 域名
host: 'localhost',
// 打包进度
progress: true,
// 自动打开浏览器
open: true,
// 除了一些基本的启动信息以外,其他的内容都不要显示
quiet: true,
// 服务器代理 --> 解决开发环境跨域问题
proxy: {
// 一旦 devServer 服务器接受到 /api 开头的请求,就会把请求转发到另一个服务器
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写: 将 /api 去除
pathRewrite: {
'^/api': ''
}
}
}
}
# package.json 中的 scripts 中配置命令
"serve": "webpack-dev-server"
1.7、加载器
1.7.1、加载器概述
在实际开发中,webpack 只能打包处理以 .js 为后缀的模块,其他非 .js 后缀的模块 webpack 默认处理不了,而需要调用 loader 加载器才能正常打包,否则会报错!
loader 加载器可以协助 webpack 打包处理特定的文件模块了,例如:
- sass-loader 可以打包处理 .scss 相关的文件
- css-loader 可以处理 css 相关的文件
- babel 可以处理 js 兼容模块
- 配置图片处理 …
1.7.2、打包处理 css 文件
正如前面所说,webpack 默认不能打包 css 文件,如果在没有安装 css 加载器的时候打包,包含 css 文件的项目则会报错:
我们需要安装一个 CSS 的加载器才能让 webpack 帮助我们打包 css 文件。
所以要想打包 css 文件,则需要安装 css 加载器,该加载器的安装命令为:
npm i -D style-loader@2 css-loader@5
安装好需要的加载器后需要对 webpack 进行配置,告诉 webpack 当遇到 css 后缀的文件应该交由哪个加载器去处理。在 webpack 打包命令对应的 module 的 rules 数组中添加 css-loader 规则:
module: {
rules: [{ test: /\.css$/, use: ["style-loader", "css-loader"] }],
}
在写加载器 use 的时候,需要注意:
- use 数组中指定的加载器顺序是固定的
- 多个加载器调用的顺序是:从右向左、从下往上调用(倒序执行)
在配置好对应的 css 加载器后,webpack 才能打包对应的 css 文件
1.7.3、打包处理 scss 文件
# 安装css预处理loader
npm i -D sass-loader@10 node-sass@5 style-loader@2 css-loader@5
# loader配置
module: {
rules: [
// scss处理
{
test: /\.scss$/,
// 执行顺序 从右到边,从下到上
use: [
"style-loader",
"css-loader",
"sass-loader"
]
}
]
}
1.7.4、抽取单个 css 文件
# 安装插件
npm i -D mini-css-extract-plugin@1
# 引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
# loader 配置
module: {
rules: [
// scss 处理
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
}
# plugins 配置
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css',
})
]
1.8、配置图片处理
# 安装
npm i -D url-loader@4 file-loader@6 html-loader@1
# loader配置
module: {
rules: [
// 图片处理
{
test: /\.(png|jpeg|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 图片小于 8kb,就会被 base64 处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 打包后的路径和文件名称 [ext]扩展名
name: 'img/[name].[ext]',
// 打包后的文件指定访问路径前缀
publicPath: '/'
}
}
]
},
{
test: /\.html$/,
// 处理 html 中的 img ( 负责引入 img ,从而能被 url-loader 进行处理)
loader: ['html-loader']
}
]
}
1.9、处理静态资源
像项目中字体资源是不需要进行打包处理的,可以直接的通过复制方式给打包到目标目录中
# 安装
npm i -D copy-webpack-plugin@6
# 引入
const CopyPlugin = require('copy-webpack-plugin')
# plugins 配置
plugins: [
new CopyPlugin({
patterns: [
{
// 来源
from: path.resolve('./src/iconfont/'),
// 目标
to: path.resolve('./dist/iconfont')
}
]
})
]
1.10、js 兼容处理
webpack 在不需要引入任何 loader 可以对于 js 进行打包处理,但是它不会对于 js 兼容性进行任何的处理,而我们编写的项目是需要在不同的浏览器中运行的,此时就需要对于 js 的兼容性在打包过程中进行对应的处理。使用 babel 来完成对应的 js 兼容处理
# 按需加载进行兼容性处理
npm i -D babel-loader@8 @babel/core@7 @babel/preset-env@7 core-js@3
# loader配置
module: {
rules: [
// js 兼容处理
{
test: /\.js$/,
// 排除
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js 版本
corejs: 3,
// 兼容性做到哪个版本的浏览器
targets: {
chrome: '75'
}
}
]
]
}
}
]
}
]
}
// ts 处理
npm i -D typescript ts-loader@6
{ test: /\.ts$/, loader: "ts-loader" }
1.11、路径别名与导入后缀省略
// 解析模块的规则
resolve: {
// 配置解析模块路径别名:优点简写路径,缺点路径没有提示
alias: {
// 定义一个@变量,可在import引入时使用
'@': path.resolve('./src')
},
// 配置省略文件路径的后缀名称 import '@/index'
// 如果省略,建议文件名称不要重名了
extensions: ['.js', '.jsx' ,'.ts','.vue']
}
1.12、tree-shaking
tree-shaking 是 webpack 中自带的功能,其作用是去除项目中无用代码 ( 一般指的都是自己所写代码 ),减少代码体积(涉及到第三方类库,往往不一定有效。)
前提:
- 必须使用 es6 模块化
- 开启 production 环境
在 package.json 文件中添加了 "sideEffects": false 表示所有代码都没有副作用 ( 所有代码都可以进行 tree shaking )
问题:可能会把 css 的 @babel/polyfill (副作用) 文件删除掉
解决:"sideEffects":["*.css"]
webpack 配置
package.json 中配置
1.13、代码分割
在做一些单页应用中,若不做任何处理,所有项目文件会打包为一个文件,这个文件非常的大,造成网页在首次进入时比较缓慢。做了代码分割后,会将代码分离到不同的chunk中,然后进行按需加载这些文件,能够提高页面首次进入的速度,网站性能也能够得到提升。
实现方案:
- entry 多入口实现分割
- optimization 配置实现分割
- import 动态导入实现代码分割 ( webpackChunkName )
- externals 忽略不打入的包
1.13.1、entry 多入口实现分割
1.13.2、optimization 配置实现分割
module.exports = {
optimization: {
splitChunks: {
//有三个可选值:initial(同步)、async(异步)、all(全部),默认为all
chunks: 'all',
// 代码块最小字节 默认为30kb
minSize: 0,
// 模块被引用的次数
minChunks: 1,
// 限制异步模块内部的并行最大请求数 默认5
maxAsyncRequests: 2,
// 限制入口的拆分数量 默认3
maxInitialRequests: 1,
// 打包后的名称分隔符
automaticNameDelimiter: '~',
// 拆分块的名称。提供 true 将根据块和缓存组键自动生成名称 vendors~xx.js
name: true,
cacheGroups: {
vendors: {
chunks: 'all',
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
chunks: 'all',
// 最小代码块字节
minSize:0,
// 最少被引用几次
minChunks: 2,
priority: -20
}
}
}
}
};
1.13.3、import 动态导入实现代码分割 ( webpackChunkName )
1.13.4、externals 忽略不打入的包
例如项目中使用从 CDN 引入 jQuery,而不是把它打包进来使用
1.14、通过 Webpack 搭建 React
安装解析 react 的相关 babel 和插件
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react => jsx
npm i -S react react-dom
进行 loader 相关配置
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: 3,
// 兼容性做到哪个版本的浏览器
targets: {
chrome: '75'
}
}
],
'@babel/preset-react'
]
}
}
]
}
]
}
在打包入口文件中引入 React 并进行单页面应用的渲染
# index.js 文件
import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
ReactDom.render(<App />, document.getElementById('app'))
# App.jsx 文件
import React from 'react'
class App extends React.Component {
render() {
return (
<div>
React 的 App 项目应用
</div>
);
}
}
export default App
1.15、通过 Webpack 搭建 Vue 项目