ES Modules基本特性
自动采用严格模式,忽略’use strcit’
每个ESM模块都是单独的私有作用域
ESM是通过CORS去请求外部JS模块的
ESM的script标签会延迟执行脚本
ESModules中可以导入CommonJS模块
CommonJS中不能导入ESModules模块
CommonJS始终只会导出一个默认成员
注意 import不是解构导出对象
Webpack
Webpack是一个现代JS应用程序的静态模块打包器(module bundler)
模块:模块化开发,可以提高开发效率,避免重复造轮子
打包:将各个模块,按照一定的规则组装起来
特点
- 功能强大:打包 构建 发布Web服务
- 学习成本高
构建(转换):把不支持的代码,转成支持的代码
打包(合并):把多个文件合并成一个文件
Webpack的功能
- 将多个文件合并打包,减少http请求次数从而提高效率
- 对代码进行编译,确保浏览器兼容性
- 对代码进行压缩,减小文件体积,提高加载速度
- 检查代码格式,确保代码质量
- 提供热更新服务,提高开发效率
- 针对不同环境,提供不同的打包策略
Webpack核心概念
入口,出口,加载器,插件,模式,模块,依赖图
Webpack核心概念 入口
- 打包时,第一个被访问的源码文件
- 默认是src/index.js(可以通过配置文件指定)
- Webpack通过入口,加载整个项目的依赖
Webpack核心概念 出口
- 打包后,输出的文件名称
- 默认是dist/main.js(可以通过配置文件指定)
Webpack核心概念 loader(加载器)
- 专门用来处理一类文件(非JS)的工具
Webpack默认只能识别JS,想要处理其他类型文件,需要对象的loader
- 命名方式:xxx-loader(css-loader|html-loader|file-loader)以-loader为后缀
常用加载器:webpackjs.com/loaders
Webpack核心概念 plugin(插件)
实则loader之外的其它功能
Plugin是webpack的支柱,用来实现丰富的功能
命名方式:xxx-webpack-plugin(html-webpack-loader)以-webpack-plugin为后缀
常用插件:webpackjs.com/plugins
Loader和Plugin本质上都是npm包
Webpack核心概念 模式
用来区分环境的关键字
不同环境的打包逻辑不同,需要区分
三种模式
- development:自动化打包速度,添加一些调式过程中的辅助
- production:自动化打包结果
- none:运行最原始的打包,不做任何额外的处理
Webpack核心概念 模块
Webpack中,一切都是模块
Js模块 一段css一张图片 一个字体文件 ...
Webpack最佳实践
1.初始化项目
mkdir myproject $$ cd myproject $$ npm init -y
2.安装Webpack
npm install -D webpack webpack-cli
3.创建入口文件
myproject/src/index.js
4.执行打包(必须指定mode)
webpack ./src/index.js --output-path ./dist --mode=development
Webpack配置文件
配置文件是用来简化命令行选择的
配置前:webpack ./src/index.js --output-path ./dist --mode=development
配置后:webpack
默认配置文件名称是webpack.comfig.js
Webpack.comfig.js是以CommonJS规范进行组织的
使用webpack的过程,大部分就是跟配置文件打交道的过程
Webpack配置文件-常用配置项
- mode(模式)
- entry(入口)
- output(出口)
- module(模块配置-不同类型文件的配置-loader配置)
- plugins(插件)
- devServer(开发服务器的配置)
Webpack打包CSS
非JS文件打包,需要对应的loader
css-loader将css转化为js(将css输出到打包后的js文件中)
style-loader把包含CSS内容的js代码,挂载到页面的<style>标签中
引入CSS(import”./css/main.cs”)
安装(npm i css-loader style-loader -D)
配置
匹配后缀名:test/.css$/i
指定加载器:use:[‘style-loader’,’css-loader’]
loader执行顺序:先右后左(先下后上)
Webpack打包less
引入less
import
"./css/main.less"
安装
npm i less less-loader -D
配置
匹配后缀名: test:/.less$/i
指定加载器:use[‘style-loader’,’css-loader’,’less-loader’]
将CSS打包成独立的文件
安装插件
npm i mini-css-extract-plugin -D
引入插件(webpack.config.js)
const
MiniCssExtractPlugin
=
require('mini-css-extract-plugin');
替换style-loade(use:[‘MiniCssExtractPlugin.loader’,’css-loader’])
style-loader:将css打包到style标签中
‘MiniCssExtractPlugin.loader’:将CSS打包到独立文件中
配置插件:(new MiniCssExtractPlugin({}))
添加样式前缀
安装
npm i postcss-loader autoprefixer -D
配置webpack.config.js
use:['MiniCssExtractPlugin.loader','css-loader','postcss-loader']
新建postcss.config.js
plugins:[require('autoprefixer')]
配置需要兼容的浏览器
Package.json中指定browserslist
校验CSS代码格式
安装
npm i stylelint stylelint-config-standard stylelint-webpack-plugin -D
引入
constStylelintPlugin
=
require('stylelint-webpack-plugin');
配置
new
StylelintPlugin({})
指定校验规则(在package.json中指定stylelint)
"stylelint":{"extends":"stylelint-config-standard"}
压缩CSS
安装
npm i optimize-css-assets-webpack-plugin -D
引入
OptimizeCssAsseptsPlugin = require('optimize-css-assets-webpack-plugin');
配置
new
OptimizeCssAssetsPlugin()
Webpack打包html
Html-webpack-plugin
生成html文件(用于服务器访问),并在html中加载所有打包的资源
指定html模板,设置html变量,压缩html
安装
npm i html-webpack-plugin -D
Webpack编辑JS
目的:将ES6+转换成ES5,保证JS在低版本浏览器的兼容性
安装
npm i babel-loader @babel/core @babel/preset-env -D
@babel/preset-env只能转译基本语法(promise就不能转换)
@babel/polyfill(转译所有JS新语法)
npm i @babel/polyfill -D
import '@babel/polyfill' //
入口文件中引入
core-js (按需转译JS新语法)
安装
npm i core-js -D
配置
按需加载 useBuiltlns: ’usage’
指定版本 corejs:3
Webpack校验JS代码格式
安装
npm i
eslint eslint-config-airbnb-base eslint-webpack-plugin eslint-plugin-import -D
eslint(校验JS代码格式的工具)
eslint-config-airbnb-base(最流行的JS代码格式规范)
eslint-webpack-plugin(webpack的eslint插件)
eslint-plugin-import(用于在package.json中读取eslintConfig配置项)
配置
eslint-webpack-plugin
constESLintPlugin
=
require('eslint-webpack-plugin');plugins:
[new
ESLintPlugin(options)],
eslintConfig(package.json)
'eslintConfig':
{"extends":"airbnb-base"}
Webpack打包图片
file-loader
将用到的图片复制到输出目录,过滤掉不用的图片
npm i file-loader -D
url-loader
file-loder的升级版,如果图片小于配置大小,会转成base64字符串
转成base64字符串后,图片会跟js一起加载(减少图片的请求次数)
npm i url-loader -D
html-loader
将html导出为字符串(负责引入img,从而能被url-loader进行处理)
npmjs.com/package/html-...
html-loader与html-webpack-plugin的冲突
原因:html-webpack-plugin会检查目标文件是否已经有loader处理,如果有其他的loader处理,html-webpack-plugin不在使用loadsh.template去处理ejs语法
解决:html-webpack-plugin中,模板文件的后缀名改为 .ejs(非.html)
Webpack打包字体
字体文件
file-loader
test:/\.(eot|svg|ttf|woff|woff2)$/i,
copy-webpack-plugin
不需要处理的其他文件,可以直接复制到输出目录
clean-webpack-plugin(每次打包之前,先删除历史文件)
资源模块(Assert Modules)
功能
资源模块是一种模块类型,允许使用资源文件,而无需配置额外loader
资源文件:字体,图片,图标,html
不用file-loader,url-loader也能加载图片和文字
Webpack4
raw-loader (将文件导入为字符串)
file-loader (将文件发送到输出目录)
url-loader (将文件发送到输出目录/转为Data URL内联到bundle中)
Webpack5
asset/resource 发送一个单独的文件并导入URL (之前通过file-loader实现)
asset/inline 导出一个资源的data URL (之前通过使用url-loader实现)
asset/source 导出资源的源代码 (之前通过使用raw-loader实现)
asset在导出一个data URL和发送一个单独的文件之间自动选择(url-loader)
Webpack Dev Server
作用:发布web服务,提高开发效率
使用
Webpack4:webpack-dev-serve
Webpack5:webpack serve
npm install webpack-dev-server --save-dev
热更新
Webpack4 hot:true
Webpack5 liveRoad:true(禁用hot)
Target: “web” (热更新只适用于web相关的targets)
Proxy(配置接口代理)
解决webpack-dev-serve下,访问接口的跨域问题
Webpack进阶
Webpack区分环境打包
- 通过环境变量区分
Webpack --env.production
Webpack.config.js中判断env
- 通过配置文件区分
Webpack.dev.conf.js
Webpack.prod.conf.js
执行打包时,指定配置文件(webpack--config webpack.[dev|prod].conf.js)
Webpack通过环境变量进行打包
命令行中设置环境变量
Webpack 4: webpack --env.production
Webpack 5: webpack --env production
webpack.config.js
读取环境变量 env.production
根据环境变量指定不同的配置
Webpack通过配置文件区分打包
通过配置文件区分环境
Webpack.dev.config.js(mode:development)
Webpack.prod.config.js(mode:production)
Webpack.base.config.js(公共配置)
Webpack-merge 将多个配置合并在一起
Webpack DefinePlugin
DefinePlugin
为配置注入全局变量
开发环境和生产环境的接口地址不同
自定义plugin
Webpack插件是一个具有apply方法的JavaScript对象。apply方法会被webpack compiler调用,并且在整个编译生命周期都可以访问compiler对象
原理:通过在生命周期的钩子中挂载函数,来实现功能扩展
生命周期
生命周期是整个生命过程的关键点
程序:初始化-挂载-渲染-展示-销毁
钩子(生命周期中的函数)
提前在可能增加功能的地方,预设一个函数
自定义loader
loader本质上是一个ESM模块,导出一个函数,在函数中对打包资源进行转换
声明一个读取markdown(.md)文件内容的loader
marked(将markdown语法转成html)
loader-utils(接收loader的配置项)
代码分离
如果把所有代码都打包到一起,可能最终的代码非常大。从而影响到加载时间,很多代码初始是不需要的。可以根据代码使用的紧急程度,将代码分割打包后按需加载。
实现代码分离
- 多入口打包:配置entry加载多个入口文件
- 提取公用模块:optimization.splitChunks.chunks:all
- 动态导入:按需加载|预加载
代码分离----多入口打包
entry(后面写成对象)
{index:'./src/index.js',about:'./src/about.js'}
output.filename(不能写成固定名称,否则报错)、
[name].bundle.js
HtmlWebpackPlugin(不同页面加载割自己的bundle)
Chunks:[‘index’]index.html加载index.bundle.js
Chunks:[‘about’]about.html加载about.bundle.js
代码分离---提取公共模块
多个页面都用到了一个公共文件,每个页面都将公共文件打包一次是不合理的。更好的办法是将公共文件提取出来
Optimization.splitChunks.chunks:all
将公共文件提取出来,单独打包
代码分离---动态导入
懒加载
默认不加载,事件触发后才加载
WebpackChunkName:“加载名称”
预加载
先等待其他资源加载,浏览器空闲时,再加载
WebpackPrefetch:true
缺点:在移动端有兼容性问题
源码映射(Source Map)
一种源代码与构建后代码之间的映射技术
通过 .md文件,将构建后的代码与源代码之间建立映射关系
为什么使用Source Map
问题:构建后的代码,出了问题后不好定位
方案:有了Source Map之后,可以快速定位问题代码
生成Source Map
Devtool:’隐射模式‘
映射模式(devtool的值)
不同映射模式的报错定位效果和打包执行速度不同
webpack4 中,一共有13种不同的映射模式
webpack5 中,一共有26种不同的映射模式
Webpack 5种的命名更新严格
webpack4:
选取合适的映射模式
开发环境 (eval-cheap-module-source-map)
生产环境 (none|nosources-source-map)
缓存
Babel缓存
cacheDirectory:true(第二次构建时,会读取之前的缓存)
文件资源缓存
如果代码在缓存期内,代码更新后看不到实时效果
方案:将代码文件名称,设置为哈希名称,名称发生变化,就加载最新的内容
Webpack哈希值
[hash](每次webpack打包生成的hash值)
[chunkhash](不同chunk的hash值不同 同一次打包可能生成不同的chunk)
[contenthash](不同内容的hash值不同,同一个chunk中可能有不同的内容)
模块解析(resolve)
resolve
配置模块解析的规则
alias:配置模块加载的路径别名
Alias:{‘@’:resolve(‘src’)}
extensions:引入模块时,可以省略哪些后缀
extensions:[“.js”,”.json”]