立即执行方法
;(function(){})()
gulp
和grunt
就是用的这种方法解决的作用域问题
gulp
和grunt
是在webpack
出现前使用的 用于自动化构建
webpack
运行于node.js
中
js中暴露 扁平对象
module.exports
其他js中调用暴露出来的js中的add
方法
使用require
引用
ctrl+~
调起控制台
node server.js
运行该js
实现了模块化
但在浏览器中引入该js 浏览器不支持
define的使用
引入外部require.js
data-main
定义入口js文件
main.js中使用require引入add.js和minus.js并调用add方法
require引入是根据index-6.html的位置来引入add.js文件的
早先前就是这样在浏览器上实现模块的拆分和加载的
BootCDN中require.js位置
ECMAScript
上面的是commonjs
下面使用ECMAScript module
来定义和导出一个模块
ECMAScript mdule
提供了一个叫 export default
的语法来暴露所需方法
使用import
引入 暴露的js文件
script标签
中一定要加type=“module”
否则报错说不能在模块外部使用import
加了type
以后 会报错 跨域
(违背跨域请求的一个安全策略)
解决方法:
在本地临时搭建一个http server
的环境
npx http-server
从网上安装一个http-server
模块
安装成功后会自动运行 根据运行的端口号或localhost
去浏览器上打开对应目录下的html文件,即可运行import
的方法
webpack
webpack可以打包js的应用程序并且支持es
的模块化以及commonjs
还可以扩展支持很多静态资源的打包 比如图片,字体文件,样式文件等等
webpack的竞品 parcel
和 rollup.js
parcel
号称零配置,开箱即用
rollup.js
用标准化的格式来编写代码
比如像es6,通过减少无用的代码来尽可能的缩小包的体积
一般只能用来打包js
如果构建一个简单的应用并快速的运行起来,可以使用parcel
如果是构建一个类库,只需要导入很少
的第三方的库,可以用rollup
如果要构建一个复杂的应用,并且集成很多第三方的库,并且还要拆分代码,还要使用静态的资源文件,还要支持commonjs
和es module
等等,只能用webpack
petite vue
vite
配vue
推出一个框架叫 petite vue
,从开发,编译,d发布,demo几乎全部都是用vite完成。vite这种基于esmodule的构建方式日益受到用户青睐
不仅可以按需编译,热模块的更新等等,还有其他的丝滑的开发体验,以及和vue3的完美结合
如何引入js代码:
直接通过script
标签来加载js
代码的问题——>全部js代码打包到一个js文件(存在作用域,文件大小,可读性,可维护性方面的问题),解决作用域问题——>应用立即执行的函数表达式,即LIFE
的方式(解决作用域问题),但这种方式存在大量的无用代码,文件体积太大,导致构建和加载的效率问题,所以不得不对代码进行拆分——>node.js
基于common.js
的模块化(这种方案的方法无法在浏览器
中运行)——>于是采取传统的browserify
以及requirejs
的方案,让类似commonjs
的模块在浏览器
里运行,只是使用起来不如commonjs
简洁——>esmodule
来直接做模块管理,但这种方式浏览器
的支持又不完整——>因此我们提出需要webpack
这样的工具,不但支持esmodule
和commonjs
两种的打包js的方案,还可以扩展一些其他的静态资源
alt+上箭头
当前行代码移动至上一行
npm : node package manger
是node
的一个包管理工具
安装webpack
需要npm
,把webpack
当作是一个node
的包来进行安装和管理
可以 全局/局部安装webpack
分为 webpack
主包 和 webpack-cli
安装webpack-cli可以在命令行中执行webpack命令
npm install webpack webpack-cli - -global
- -global
代表全局安装,在所有目录中皆可使用webpack
webpack -v
查看webpack
安装的版本
不推荐全局安装webpack,会使你项目的webpack锁定到某个版本里,并且在使用不同的webpack版本的项目中,可能会导致构建失败
而且在团队合作中,其他人不知道是全局安装的webpack,也会有问题
所以,推荐在 本地的 工作目录 下去安装webpack
npm init -y
安装npm
的包管理的配置文件。项目根目录下会产生一个package.json
里面的配置,学过node的会知道
npm install webpack webpack-cli - -save-dev
本地安装webpack
及wepack-cli
安装完会出现一个node_modules
一个package-lock.json
和一个package.json
命令行输入webpack
直接打包,会出现一个dist
文件夹,里面是打包好的文件
wepack - -stats detailed
显示详细的打包信息
npm uninstall wepack webpack-cli - -global
卸载全局的webpack
和webpack-cli
再在命令行直接输入wepack
打包会报错
,报没有改文件或目录
使用本地安装的webpack(npx):
需使用npx
,npx
依托于npm
,如果npm
安装好了,npx
可以直接使用
npx
表示当前文件夹里有没有你想要去运行的这个命令
npx
当前目录中找不到会去上级目录中继续寻找
命令行输入 npx webpack
,会正常执行本地webpack
打包
自定义wepack配置:
命令行 pwd
显示当前工作目录
webpack - -help
查看终端命令
写法:
npx webpack - -help
- -config
:webpack指定的根
- -entry
:指定入口
- -mode
:指定模式
写法:
npx webpack - -entry ./src/index.js - -mode production
production
表示生产环境
默认会生成一个包含main.js
的dist
文件夹
这样的写法不方便也不直观,还不能保存我的的一些配置
通过配置文件配置参数
新建webpack.config.js
,该文件名固定,因为这个文件需要webpack
去自动读取
因为在node中运行,所以定义模块要使用nodejs的commonjs
模块
所以使用moudle.exports
去定义
entry
入口
output
出口
报错原因:path
必须是一个绝对路径
获取绝对路径:
引入path:const path = require(“path”)
path.resolve
参数:
__dirname
等于该文件的物理路径,也就说当前文件所在的路径02-setup-app
“./dist”
相对路径
完整写法:
不写mode
会报错说mode
未设置
成功后dist
文件夹中会出现一个bundle.js
(bundle的名字是在webpack.confih.js
中设置的)
html页script
标签引入改为./dist/bundle.js
,html代码上点击右键选择复制路径,打开浏览器
查看效果
自动引入webpack资源:
使用webpack插件
流程:
plugins
plugins
即插件
途中js模块数量不固定,可多可少,只是体现js可能会依赖一个或多个其他的js文件
如果js引用css文件 需要loader
加载器
webpack
会把这些依赖的关系记录下来,然后交给webpack
的编译器,编译器通过加工以后会生成 目标文件
比如js文件和css文件(不一定,具体看打包的是什么文件,图中只是大致举例)
编译的过程需要一些工具的帮忙完成一些特定的任务,比如打包优化,资源管理等等。这些工具就是所谓的插件
webpack官网,点击DOCUMENTATION
下的Plugins
就会出现webpack5
中使用的一些插件
分成三组:
Community
社区的插件
Webpack
即webpack
内置的一些官方插件
Webpack Contrib
就是contribution
,是webpack
第三方的一些插件
本地安装 -D
npm install html-webpack-plugin -D
安装插件
HtmlWebpackPlugin
用来解决bundle.js
手动修改的问题
webpack.config.js
中通过require
引入html-webpack-plugin
,并添加plugins
数组来配置插件
在文件夹目录下执行npx webpack
打包命令
执行成功后,dist
的文件夹中会出现一个新的index.html
,该html中的head
标签中,有引入bundle.js
的script
标签
修改webpack插件配置基于哪个页面:
template
:模版
filename
文件名
inject
:引入的标签生成的位置(推荐使用body
)
再次运行npx webpack
命令
成功后,dist
中app.html
内部结构
bundle
引入标签已不在head
中
清理dist文件夹:
webpack.config.js
中的output
中,添加clean:true
再次运行npx webpack
,配置中没有的
html文件在dist
文件夹中会被自动删除
HtmlWebpackPlugin
(插件的一种)用来解决bundle.js
手动引入bundle.js
问题
mode
选项:
webpack.config.js
中mode
设为development
,设置为开发模式
bundle中./src/hello-word.js
代码下方的eval
的显示不适合代码的观察及调试,需要转化
使用source map
来调试:
webpack.config.js
中添加devtool:“inline-source-map”
使用source map
,如果代码报错,浏览器上报错的行数
才会正确
并且bundle.js
中原先eval
格式的代码也变为了正常格式的代码
这高亮的代码就是未打包之前的js文件中的代码
使用source map ,如果代码报错,浏览器上报错的行数才会正确,指向的是 源文件
的代码的位置
- -watch
会时时监听,自动构建
每次手动运行npx webpack很麻烦 可以在npx webpack 后添加- -watch
,下次有文件更改会自动构建
虽然- -watch
会时时监听,保存后 会自动构建,但需要看改动后的效果,还是必须每次都刷新一次浏览器页面
如何自动刷新浏览器显示改动内容,使用webpack-dev-server
webpack-dev-server
有live reloading
时时重新加载的功能
npm install webpack-dev-server -D
安装
webpack.config.js
中添加devServer
对象
devServer
中添加 static
:根目录物理路径
这里物理路径设置的是dist
npx webpack-dev-server
运行
运行成功后打开localhost
显示Hot Moudle Replacement enabled
表示的模块替换已经生效
Live Reloading enabled
表示实时更新生效
webpack-dev-server
其实并没有输出任何物理文件,而是把打包的bundle
文件放到了内存
里
证明:
把dist
文件夹删除
,仍能照常运行,控制台重新运行服务,仍能正常运行,修改代码后也仍旧可以自动刷新,正常展示修改部分
这样可以提高我们的开发效率,webpack
的编译效率也提高了
资源模块:
asset moudles
来引入任何的其他类型资源
资源模块:asset moudle
资源类型:asset moudle type
type:
asset是一个文件夹
asset/resource
会发送一个单独的文件并导出url
asset/inline
会导出一个资源的Data URL
asset/source
会导出资源的源代码
asset 会在导出一个 Data URL和发送一个单独的文件之间自动进行选择
写法:
添加type
属性,值为 “asset/resource”
资源类型 共4种
asset moudles
内置资源模块
早期处理使用类似Grunt或Gulp来处理资源,将src
文件夹里的文件移动
到dist
或者build
目录中
resource资源:
在webpack.config.js
中加入module
对象,来配置模块
moudle
中添加rules
数组 ,通过配置多个对象,来加载不同类型的文件
添加test
属性,冒号后加一个正则表达式 ,来去定义我们加载文件的类型
例如:/\.png$/
png
加$
表示 ,以png
作为扩展名(后缀)的 这样类型的文件
添加type
属性,值为 “asset/resource”
把asset
文件夹及部分js放入src
文件夹,在要使用png图片的js中引入图片并使用
npx webpack
命令打包,打包成功后,在dist
文件夹中会出现
一个系统自动命名
的png
文件
然后在浏览器上预览一下:
使用
wepack-dev-server
npx wepack-dev-server - -open
- -open
会自动打开浏览器
在浏览器
上 检查代码,图片src地址是localhost:+ ip地址+/+dist文件夹中自动生成的png文件名
默认文件打包
存在dist
目录下,并自动生成文件名
自定义文件名及文件目录
两种方法
第一种:
在output
中去添加属性assetModuleFilename
,可以设置文件名和路径
例如“images/test.png”
但不可能所有图片都叫一个名字,所以要拼接文件名
可以使用webpack系统自带的默认的生成文件明的方法,——就是[contenthash]
,表示根据文件的内容来生成一个哈希
的字符串
,扩展名可以使用原资源
的扩展名,[ext]
来表示扩展名
assetModuleFilename:images/[contenthash][ext]
然后npx webpack
重新进行一下编译,dist
文件夹下会多出一个存了原文件名的png
文件的叫images
的文件夹
第二种方法:
在moudle
中的rules
中添加名为generator
的对象,里面的filename
属性可以设置文件名及路径
如果output
和moudle
的rules
的generator
中都定义了文件名及路径的话,generator
的优先级更高,并且不会两个配置都执行,只会执行一次优先级高的那个,所以优先级低的那个也不必删除,可以以防以后能用的到
inline资源:
npx webpack编译成功后,dist
文件夹中不会生成新的资源文件,因为是inline
格式。运行到浏览器
上查看,检查图片链接,图片链接为data:image/svg+xml:base64
的base64
格式的图片链接,image/svg
的svg
取决于webpack.config.js
中的rules
中的type
属性为asset/inline
的对象的test
属性
source资源:
用于导出资源的源代码
webpack.config.js
配置文件中,rules
中新增对象,type
为asset/source
,test
为txt
结尾的格式
生成一个div
,用于显示txt
文本内容
npx webpack
打包
成功后dist
文件夹中仍不会生成新的资源文件,只能在浏览器
上看效果:
npx webpack dev-`server - -open
点击app.html
显示内容
通用资源类型asset
:
在导出一个url和发送一个单独的文件这2种方式之间自动选择
这种情况下,会生成asset/resource
的类型文件—系统命名的本地资源文件
如果新生成的资源文件小于8k,生成的就是inline
格式的资源文件—dist文件中没有,浏览器上base64格式
调整文件大小的临界值:
webpack.config.js
中rules
中的type
为asset
的对象中添加parser
对象,其中添加属性dataUrlCondition
,值为对象
,对象中添加属性maxSize
,值为图片大小
,例如4*1024*1024
npx webpack
成功后,发现dist
中已经没有之前那个自动生成的本地图片文件,打开浏览器,图片链接变为base64
格式
loader:
两个属性
test
识别哪些文件被转换
use
在定义转化时,应该使用哪个loader
安装完css-loader
后,webpack.config.js
中的rules
中添加对象,属性test
,值为/\.css$/
,属性use
,值为css- loader
引入对应css
文件
使用css
文件中的样式hello
运行npm webpack-dev-server - -open
发现样式未生效
必须再安装一个loader,style- loader
进入项目根目录,安装style- loader
npm style-loader -D
回到wepack.config.js
,修改rules
中css后缀
文件配置,use
改为数组,[‘style-loader’,’css-loader’]
先要使用css-loader
打包文件,识别css文件,是打包没有问题,然后再使用style- loader
把css
样式放置到页面上
所以数组中css-loader顺序在style-loader之后
,其实是先写
的css-loader
npx webpack
,然后npm webpack-dev-server - -open
发现字体变红
检查代码,class hello
添加在了boday
上,head
标签里多了个style
标签,标签中多了个hello
的样式
webpack
配置文件中,style-loader
和css loader
的顺序不可修改
loader的链式调用
webpack支持loader的链式调用,链式的每一个loader都可以怼我们的源进行转换,而且转换是逆序的,第一个loader(css-loader)会将结果或者是转换以后的源,传递给下一个loader,最后webpack希望style-loader会返回一个js
解析less文件
安装less-loader
修改webpack
配置文件中的为对象
修改扩展名,支持css和less文件
数组中**添加**less-loader
,位置顺序固定不可修改
新建一个less文件
引入less文件
npm webpack
然后 npm webpack-dev-server - -open
查看浏览器效果,检查代码,发现head标签中多了一个style标签,其中包含一个body的样式
以上是使用三个loader,解析了一个less文件
抽离和压缩css:
上一部分使用loader加载的css的代码是和html在一起的,现在要把style标签里的代码放到一个单独的文件里通过link标签去加载它
安装插件 mini-css-extract-plugin
npm install mini-css-extract-plugin -D
这个插件是基于webpack5
构建的,所以要使用它,必须在webpack5
的环境下才可以
安装完,去webpack
配置文件中去引入插件
在plugins数组中实例话一下该插件(MiniCssExtractPlugin这个定义的常量)
原来是使用style-loader去放置css样式,现在需要抽离到单独的文件中,那就不需要style- loader了,使用MiniCssExtractPlugin.loader来代替
npm webpack 成功后 ,dist文件夹中多了一个main.css的的文件
再看app.html中,已经没有style标签了,但多了一个link标签
再次运行到浏览器上查看,查看代码head标签中原来的style标签已经消失,但head标签中多出一个link标签
指定打包后css文件的文件夹的名字及文件名
实例话MiniCssExtractPlugin中添加filename属性,值为styles/[contenthash].css(文件夹/文件名.后缀)
npx webpack成功后 dist文件夹中结果
css文件中的代码没有压缩,在生产环境中,压缩一下会提升加载的效率
通过安装 css-minimizer-webpack-plugin
来实现压缩
npm install css-minimizer-webpack-plugin -D
webpack
配置文件中,定义一个常量
引入css-minimizer-webpack-plugin
wepack配置文件中添加optimization对象及其属性,这是个优化配置
然后还必须把weboack配置文件中的mode的值从development改为production
执行npx webpack
然后打开css文件查看 ,发现代码已压缩
如何加载images图像
写样式
使用样式
mode改成development
npm webpack 成功后css文件内容
加载fonts字体
css文件中载入字体文件
并在.icon样式中使用
在html中使用class icon样式
字体文件,需要像文本一样去加载一个文本代码(本项目中下载的字体的文本代码为),必须用innnerHTML,不能使用text
加载数据:
其实之前的图片,icon图标,文本文件也都是数据
安装csv-loader
和xml-loader
npm install csv-loader xml-loader -D
配置文件中添加配置
index.js
中引入xml
文件和csv
格式文件
并赋值给变量
console打印两个变量的值
npx webpack
然后npx webpack-dev-server
xml文件会转换成一个object对象,csv文件会被转化为一个Array数组
自定义JSON模块parser
json5格式是json的升级,能写注释,而且key可以不用双引号
值可以用单引号,并且值可以使用\r\n这样的转义字符
npm install toml yaml json5 -D
导入安装的三个模块
添加配置
必须 parser解析器,属性parse去定义
去项目中使用
去index.js引入三个格式的文件(先找三个文件放入项目中)
打印三个已引入的文件
及其owner.name
npm webpack-dev-server
去浏览器看效果
三个文件的数据及owner下的name都成功显示
使用 babel- loader:
js文件中的代码npm webpack打包成功后,bundle.js
中代码原封不动的打包进文件
js文件中包含es6代码async awit浏览器支持es6所以能执行,如果浏览器不支持es6
需使用babel-loader
转化为es5
代码
await
是等待promise
的返回结果,异步await
必须带async
浏览器中代码原封不动打包使用
babel- loader解析转化js
安装 npm install babel-loader @babel/core @babel/preset-env -D
webpack配置文件添加js文件后缀配置
js包含本地自己写的js,还有外部node modules中的js,node modules中的js不需要解析,所以得排除
对象中添加exclude:/node_modules/
npx webpack
然后运行浏览器
打开检查代码报错,说缺少regeneratorRuntime
回到bundle.js中,发现确实使用了regeneratorRuntime
regeneratorRuntime报错 证明babel配置有问题
安装 npm install @babel/runtime -D
@babel/runtime这个包含的是regeneratorRuntime运行的时候需要的内容
再安装 npm install @babel/plugin-transform-runtime -D
这个插件会在需要regeneratorRuntime的地方自动require导包,然后编译的时候就会需要它
在配置文件中需要使用的地方添加 @babel/plugin-transform-runtime 插件配置
npx webpack
启动服务运行浏览器
发现原先的图片都正常显示,检查代码也不报错了
表示那个async await能正常运行了
代码分离方法:
代码分离是webpack最引人注目的特性之一
这个特性能把代码分离到不同的bundle中(bubdle是我们打包出来的文件)
然后进行按需加载或者并行加载
代码分离可以用于获取更小的bundle,以及控制资源加载的优先级。如果使用合理,会极大的影响加载时间
常用的代码分离分三种
第一种叫配置入口节点,使用entry
配置手动的分离代码
这种方式有个问题:如果大户多个入口,那么这些多个入口共享的文件会分别在每个包里去重复打包
所以提出了第二种,叫做防止重复的分离方法。可以的入口的地方使用对应的方法去重和分离代码
使用入口起点:
修改入口节点,是目前为止最简单直观的分离方法
新建一个文件another-module.js
这个js需要在入口中做个配置
wepack.config.js中 entry改为对象,这样可以配置多入口
npx webpack
会报错,多个chunks打包完出现了一个same filename bundle.js的错误,表示多个入口使用的是一个出口的文件名bundle,所以必须对两个入口的文件起不同的文件名
报错图:
只需要修改一下filename
即可
修改后:
[name]
可以拿到入口文件配置中key
的名字(本项目中,指的是entry
对象中的index
和another
)
改为[name].bundle.js
npx webpack 运行成功后 看到运行的详细信息中两个打包完的文件的大小一个为1.3mib,一个为943kib,都很大
文件大的原因:
index.bundle.js是因为使用了babel-loader,它会把一些js的方法打进去
another.bundle.js是因为引用了loadash,这个loadash被打包到了another.bundle.js里
npx webpack打包完成功后 dist文件夹中会出现 index.bundle.js文件和another.bubdle.js文件
分为两个script标签引入
运行浏览器,查看代码,发现成功打印出 Another module loaded!
如果index.js也使用loadash
index.js中引入loadash
打包 npx webpack
打包成功后 再去相信信息中查看两个js文件的大小,发现another.js大小仍是1.38MiB不变,index.js的大小变为了2.29MiB,所以证明index.js也把loadash打包到代码里了
重新启动服务,打开浏览器,找到对应页面,检查代码,发现打印了 index module loaded!和 Another module loaded!
也就是说明代码成功运行了,但loadash应该是共享的代码,但使用多入口的方法,它分别把各自引用的通用的包(例如loadash)都分别打到各自的chunk里并引入到各自的bundle中
所以多入口要防重复
防止重复:
修改入口entry配置
dependOn表示,如果共享为loadash的这样的一个模块时,就会把它抽离出来并取名为shared
npx webpack成功后
打包信息会多出一个shared.bundle.js 就是把loadash单独抽离出来放到了这个chunk里了,index和another的大小都变为之前的大小
app.html中会多一个script引入shared.bundle.js的标签
使用webpack内置的插件split-chunks-plugin,也可以把模块依赖的一些公共文件给处理成单独的chunk
重新配置entry
配置optimization中添加对象splitChunks,添加属性chunks:‘all’,来实现代码的分割,并且把公共的代码抽离到单独的文件里
会自动的做公共的代码的抽离
npx webpack后 执行的信息里除了index和another会多出两个bundule,一个是loadash 还有一个是命名很长的使用到的公共文件名组合成名字的bundle
第三种代码分离的方法
动态导入:
新建一个async.js文件,import引用loadash,异步使用.then,getComponent方法返回的是一个promise
这么写是为了单独抽离loadash文件
去index.js引入这个js
webpack配置文件中入口也只导入一个index.js
npx webpack成功后,信息中会出现一个loadash_js.bundle.js
证明分离成功
之前的第二种抽离是静态抽离
静态抽离和动态抽离一起使用,把entry改成第二种,webpack的配置也都使用第二种的,动态抽离的写法不变(entry不改成一个)
动态导入的应用:
第一种,懒加载
新建一个math.js文件
在index.js中创建一个按钮,添加点击事件,点击事件import导入math.js方法
npx webpack后
dist中会多一个src_math_js.bundle.js文件
文件里包含了add和minus这两个方法,可见这个模块是被单独的处理出去了
运行浏览器,检查代码,选中Network,刷新,发现其中并没有src_math_js.bundle.js
点击按钮后
才会出现src_math_js.bundle.js
再点击Console,打印出9
证明src_math_js.bundle.js这个模块在页面第一次加载时不加载,只有用户点击后才加载。不点击就不会在服务器上加载,这样能节省我们网络的流量
math.js打包完的文件明是可以修改的,修改在index.js中import方法的参数。叫做魔法注释
import的参数中加入一个注释,注释中的webpackChunkName的值就是新的命名(本项目中为‘math’)
npx webpack后,dist中文件名变为math.bundle.js
math后的bundle.js是因为在webpack的配置文件中的output中配置了[name].bundle.js
预加载/预获取
动态导入的第二个应用:预加载/预获取
webpack4.6
之后才可使用
prefetch
预获取
preload
预加载
预加载:
在index.js中的import方法中的魔法注释中,添加webpackPrefetch:true
npx webpack后dist
中不会有变化,打开浏览器
,检查代码,选中Network
,,刷新后,发现已经有math.bundle.js
,
点击按钮后,会再次执行math.bundle.js
然后Console中会打印9
只打印了一次,证明第一次加载了js但不会执行
通过prefetch
加载js
,在Element
中会多一个link
这个link(预加载)的意义是,当我们首页面的内容都加载完毕,在网络空闲的时候,再去加载我们打包好的math.bundle.js
,这种方式比刚才的懒加载
还要优秀
这就是所谓的prefetch
preload
写法也是魔法注释中添加webpackPreload:true
npx webpack后dist也不会有改变,打开浏览器,打开Network,刷新,并没有math.bundle.js,点击按钮后,会出现math.bundle.js
证明preload
和懒加载效果类似
所以对我当前需求比较好的选择还是prefetch
预加载也叫异步加载
动态导入就是使用import
导入,同时还可以用preload
来实现页面模块的并行加载
缓存:
client
指浏览器
缓存: 我们可以通过命中缓存以降低网络流量,使网站加载速度更快。然而我们在部署新版本的时候,不更改资源的文件名,浏览器可能会认为你没有更新,那就会使用它的缓存版本。
由于缓存的存在,我们需要获取新的代码的时候,就是下面的内容:
webpack
配置中output
中的filename
修改为[name][contenthash].js
从而使文件名随着文件的内容的变化
而变化
这样就不怕浏览器缓存了
缓存第三方库:
第三方库例如loadash
就是说把loadash
这种共用的第三方的代码单独打包,缓存到浏览器里,这样只有我们自己的代码发生变化的时候,我们才可以去更新,但是第三方的代码始终可以使用浏览器缓存
的内容
那就得需要对第三方的代码做一个缓存
实现方法:
dist下的vendors-node的文件
把这两个文件单独打包并缓存到浏览器里
这两个文件是始终不变的,那这个文件名也应该始终不变
修改webpack
配置文件中的splitChunks
的配置
splitChunks
内容改为catch Groups
对象,对象内部为vendor
对象,该对象的参数为test
,name
及chunks
。值参照下图
npx webpack后,原dist
中的两个vendor
包变为vendors.bundle.js
(内容都被打包进这个js,vendor
这个名称是上面vendor
对象的name
参数的值决定的,上图中name的值就是vendor)
将所有的js
文件放到一个单独的文件夹中:
修改output
的filename
并在其值中添加上scripts
目录
npx webpack后打开dist 发现内部分有images,scripts及styles目录等
app.html中也都加载了这些文件
运行浏览器 检查代码无报错,证明打包成功
至此实现了全部资源的打包
拆分开发环境和生产环境配置:
现在只能手工的来调整mode选项来调整生产和开发环境的切换(development开发环境 production生产环境)
并且很多的配置在生产环境和开发环境中,是存在不一致的情况的。比如:开发环境没有必要设置缓存,生产环境还需要设置公共路径等等。
公共路径:
就是publicPath
配置
可以使用它来值定应用程序中所有资源的基础路径
在webpack配置文件中output中**添加publicPath
,值为“http://localhost:8080/”*
*
npx webpack后 打开app.html在所有资源的引入前面都多了一个http://localhost:8080
的域名
原来:
修改后:
环境变量:
npx webpack - -env production
修改webpack配置文件 把原来midule.exports
等于 的 对象改成一个函数,函数的参数为env
,并打印env
打印env.local
运行npx webpack - -env production - -env goal=local
运行成功后 具体信息中会直接打印出local 字符串
修改mode的值,命令行中是否有env.production,有就自动使用production,没有就用development
代码压缩正常使用webpack开箱即用的terser即可,但如果配置过minimizer(做过css代码压缩),terser还需再次进行手动下载及配置
npm install terser-webpack-plugin -D
webpack配置文件中引用terser-webpack-plugin
插件
然后再在minimizer中实例话变量TerserPlugin
npx webpack - -env production
在生产环境打包
打开dist,发现之前打包的代码都已经压缩,但vendor会多出一个LICENSE.txt的文件
如果npx webpack - -env development
打开dist 发现打包的代码并没有压缩,所以证明只在生产环境代码压缩
拆分配置文件:
如果mode的配置都用判断和三元运算之类的来判断会很糟糕,是否能简化这一配置
方法:
把配置文件拆成两个配置,一个专门做生产环境的配置,一个专门做开发环境的配置
再建一个名为webpack.config.dev.js(用于development开发环境)
把moudle.exports等于 从函数改回 对象(扁平化)
开发环境中filename关于文件名的缓存[contenthas]不需要了,删除
开发环境中没必要做publicPath,删除
mode改为development
开发环境需要调试代码,所以devtool是需要设置的,保留
开发环境需要启动服务,所以devServer需要配置,保留
开发环境不需要压缩代码,所以optimization中的minizer不需要了,删除
我们需要把第三方的包打到一个文件里,cacheGroup保留
删除配置文件中已经去除不用的依赖(css压缩和terser插件)
以上就是开发配置
运行写法也不一样,因为需要使用指定的自定义的配置文件,需要npx webpack -config
或简写-c
来指定
例:npx webpack -c ./config/webpack.config.dev.js
运行成功后config
文件夹中多出一个dist
文件夹,config
文件夹外部文件均未受到任何影响
为什么打包在config文件夹中,而不是替换外部的dist文件夹?因为output的路径path配置未修改,./应该写成…/
然后再次使用npx webpack -c ./config/webpack.config.dev.js
发现dist内文件成功被替换了
生产环境配置:
把moudle.exports等于 从函数改回 对象(扁平化)
把return去掉
把最下面多出来的}去掉
filename缓存和publicPath都需要,不用改
path的值从./dist改成…/dist
因为打包成功生成的dist需要在上一级目录里
mode改为production生产环境
生产环境不需要devtool,删掉
生产环境下也不需要devServer ,删除
minimizer压缩需要,不需要改
npx webpack -c ./config/webpack.config.prod.js
如果要起服务 那就得运行development的环境的配置文件
带dev的那个
npx webpack serve -c ./config/webpack.config.dev.js
npm脚本:
每次打包或者启动服务的时候都需要输入一串长命令,能否简化优化一下
在当前目录下新建一个packqge.json文件,外部的package是整个module执行的
然后把其他配置斗加上
去掉npx是因为在本地已经有我们的包了,所以不需要npx了
在本地使用的话能使用,是因为运行的是node_modules下的bin下的webpack
这样使用npm run start就能运行server
使用npm run build就能打包(使用生产环境的配置js)
关闭提示信息 修改webpack配置文件performance的hints值为false
提取公共配置:
新建一个weboack.config.common.js
作为一个dev
和pro
两个环境公共的内容放进去
output
的filename
不一样删除
output
的publicPath
不一样删除
mode
(环境)不一样删除
devtool
不一样删除
devServer
不一样删除
optimization
的minimizer
(压缩,只有生产)不一样删除
然后再把dev
和pro
中的公用部分删除
dev:
pro:
以及这五个配置
合并配置文件:
全局安装webpack-merge
npm install webpack-merge -D
新建一个webpack.config.js,用于合并拆分的三个webpack配置文件
引入webpack-merge,再分别引入拆分的三个webpack配置文件
通过module.exports去导出,以函数的形式导出,参数为env
写一个switch case的条件判断
值为env.development的common和dev合并,值为env.production的话,common和pro合并,为defult(默认值)的话,抛出一个错误
package.json的配置scripts需要修改,start和build都改为webpack.config.js
但后面都得带上环境变量,start的值后面要加- -env development,build后添加- -env production
webpack.common.js
中output
的path
值要记得改为“../dist”