目录
webpack
webpack的前因
在网页之中引入那些静态资源
- 1:样式表
- .css .less .sass .scss
- 2:javascript脚本
- .js .ts .coffee
- 3:img
- .png .jpg .webp .gif
- 4:模板文件
- .vue .ejs
- 5:字体文件(Fonts)
- .eot .svg .ttf .woff
上述的静态资源过多后,会造成一定的影响!
-
1:加载慢
因为静态资源多,需要发起多次二次请求,使得网页的加载速度变得慢了! -
2:会存在静态资源的互相依赖问题!
-
解决方案:
1:把img图标等合并为精灵图,把图片或js合并,并且压缩一下
2:把图片转化为base64的编码格式(以字符串的形式存在!)
<img src="./1.png /> 转化为base64的方式 <img src="base64:image....
浏览器解析的时候,识别这些base64编码,转化为一个img渲染到页面(不用像 ./1.png方式,需要再发起一次请求! )
3:使用webpack来解决静态资源的依赖性问题!(因为这是使用了CommonJS的导包原理,一并把所依赖的包一起打包起来!)
webpack的介绍之 开发篇
-
概念:webpack是前端构建项目的一个工具,这个工具可以使用项目更好维护,更好把控!
-
应用场景:webpack构建项目非常适合结合单页面应用程序;不适合多页面应用程序!
-
作用:
- 1:能够处理静态资源的依赖关系
- 2:能够对静态资源的合并或压缩,减少文件的大小!
- 3:能把高级语法转化为低级语法
- 4:webpack可以转化一些模板文件 .vue(就是一个组件)等!
-
安装:
- 1:全局安装webpack
npm || cnpm i webpack -g
可以选择npm或者cnpm
webpack -v => 查看安装的版本!
会提示你安装 webpack cli 安装即可! - 2:项目之中安装webpack => 使用的最多的方式
npm i webpack -D
=> 安装到开发项目依赖!
- 1:全局安装webpack
-
最原始的打包方式(构建项目方式)
- 1:
webpack ./src/main.js ./dist/bundle.js
//=> webpack 将指定的文件(处理的文件) 打包到 指定的文件夹之中(输出路径) - 2:
webpack ./src/main.js -o ./dist/bundle.js
//上面的指令保错的话就执行这一行指令!
- 1:
-
想要使用webpack脚本命令直接构建项目的话,则需要配置文件
- 注意点:就是webpack默认情况下,只能打包 .js文件,需要打包 其他后缀名的文件 那么需要相对应的loader加载器!
- 在项目目录下,创建一个webpack.config.js文件!
- 在这个配置文件之中,需要明确的声明, 要处理的文件路径 还有要输出的文件路径
注意点:就是webpack这个项目构建工具的底层就是使用node.js开发的,因此需要使用
导出:module.exports = {}
导入:const ? = require('需要导入的模块')
const path = require("path"); module.exports = { //指定要处理的文件路径 entry: path.join(__dirname, "./src/main.js"), //指定要输入文件路径 和 文件名 output: { path: path.join(__dirname, "./dist"), //路径 filename: "bundle.js" //文件名 } }
- 配置完毕后,在终端之中,输入webpack命令即可! 但是每一次修改后,还需要输入命令,还是很繁琐,因此需要一个自动监听的服务器来实现自动监听代码更新效果。显示最新的效果!
- 在这个配置文件之中,需要明确的声明, 要处理的文件路径 还有要输出的文件路径
配置webpack-dev-server方式1
-
注意点:配置webpack-dev-server需要在上述的基本配置上添加以下的需求:
-
目的:实现实时的代码编译和刷新浏览器!
-
使用webpack-dev-server 第一种方式 => 实现文件的更新,自动刷新代码实现的效果!推荐使用的方式!
- 安装:
npm i webpack-dev-server -D
- 这个包还依赖于与webpack包(项目本地),因此还需要下载webpack包
npm i webpack -D
由于webpack-dev-server是安装在项目之中的,无法直接输入指令开启,因此还需要在package.json文件中自定义脚本命令
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server" //执行 npm run dev 后 会根据这个脚本指令,去配置项寻找暴露的配置文件执行! }
由于webpack-dev-server还依赖于脚手架,需要下载才能使用
npm i webpack-cli -D
运行的时候npm run dev 结果会开启一个服务器**http://localhost:8080/**通过这个url路径访问(浏览器)i 「wds」: Project is running at http://localhost:8080/ => 项目运行这个服务之中 (可以在浏览器中访问) i 「wds」: webpack output is served from / => 这个服务的输出文件被托管于当前文件目录 / 也就是说 (http://localhost:8080/bundle.js 可以访问!,那么就是可以在html之中,利用这个路径来导入!) // `<script src="/bundle.js"></script> html中引入! 但是大部分都是使用html-webpack-plugin 插件来自动引入的` i 「wds」: Content not from webpack is served from D:\xzl_HTML5\010vue\VueBase\day04webpack\01webpack-table 既然如此的话,
- 注意点:使用webpack-dev-server这个工具,自动打包的bundle.js文件没有打包到实际的磁盘之中,而是隐秘地托管在内存之中(其实也可以认为托管在根目录之中!但是看不着,却实际存在)
- 保存在内存之中,有着更快的写入,提高保存速度运行速度,还有与磁盘一比,写入更快!
- 安装:
-
想要编译完成后,自动打开浏览器,那么需要在package.json文件配置参数 也就是对脚本命令(dev) 在添加 --open
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --open" //注意点:这边还可以指定端口号 还有ip地址 --port 3000 --host 127.0.0.1 // --hot(热跟新,就是不再重新生成bundle.js,index.html而是以补丁的方式,往旧的文件打入新的更改,效率更高一些!) }
配置webpack-dev-server方式2 不推荐
- 使用webpack-dev-server 第二种方式 => 实现文件的更新,自动刷新代码实现的效果!
- 1:下载插件和引入插件
npm i webpack open-browser-webpack-plugin -D
- 2:在package.json文件中配置这个脚本指令
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev2": "webpack-dev-server" }
- 3:在webpack.config.js文件中创建一个服务,为了自动打开浏览器和热更新等!
module.exports = { //指定要处理的文件路径 entry: path.join(__dirname, "./src/main.js"), //指定要输入文件路径 和 文件名 output: { path: path.join(__dirname, "./dist"), //路径 filename: "bundle.js" //文件名 }, //关于插件相关的数组 plugins: [ new htmlWebpackPlugin({ //这是把html页面保存在内存之中 template: path.join(__dirname, "./src/index.html"), //就是所要复制模板,保存在内存之中 filename: "index.html" //将来在内存之中复制出来的模板,名称为index.html }), new webpack.HotModuleReplacementPlugin() ], // 关于自动打开浏览器的脚本指令 devServer: { open: true, //自动打开浏览器 port: 3000, //端口号 host: "127.0.0.1", //ip地址 hot: true, //启动热跟新,在这边的haul,需要配合插件的使用 } }
- 1:下载插件和引入插件
初步使用webpack打包构建列表隔行变色案例
执行打包 (最原始的打包方式) => 后面有着更为方便的方式
<ul>
<li>我是1个小li</li>
<li>我是2个小li</li>
<li>我是3个小li</li>
<li>我是4个小li</li>
<li>我是5个小li</li>
<li>我是6个小li</li>
<li>我是7个小li</li>
<li>我是8个小li</li>
<li>我是9个小li</li>
<li>我是10个小li</li>
</ul>
<script src="../dist/bundle.js"></script>
import $ from "jquery";
$(function () {
$("ul li:odd").css({
"background": "red"
})
$("ul li:even").css({
"background": "yellow"
})
})
webpack之plugin(插件)
html-webpack-plugin插件
- 目的:操作html的插件,可简化HTML文件的创建以服务你的webpack捆绑软件
- 把html文件生成到内存中的插件!
- 于是在内存之中保存了一份index.html文件,使用http://localhost:8080/index.html可以访问到
- 注意点:这个插件还有一个功能,就是会把那个bundle.js自动注入到index.html文件之中,因此不需要在手动导入!
- 安装:
npm install html-webpack-plugin -D
- 使用:
- 在webpack.config.js文件之中,引入这个插件,并且使用
const path = require("path"); //引入一个使得html页面生成,保存在内存之中 const htmlWebpackPlugin = require("html-webpack-plugin"); //导入的是一个构造函数 module.exports = { //指定要处理的文件路径 entry: path.join(__dirname, "./src/main.js"), //指定要输入文件路径 和 文件名 output: { path: path.join(__dirname, "./dist"), //路径 filename: "bundle.js" //文件名 }, //关于插件相关的数组 plugins: [ new htmlWebpackPlugin({ //这是把html页面保存在内存之中 template: path.join(__dirname, "./src/index.html"), //就是所要复制模板,保存在内存之中 filename: "index.html" //将来在内存之中复制出来的模板,名称为index.html }) ] }
- 最后执行 npm run dev
- 在webpack.config.js文件之中,引入这个插件,并且使用
webpack之loader(加载器)
- 注意点1:main.js是打包的入口文件,那么所有的第三方文件 .css .less .js 什么的都应该导入这个这个文件,然后一并打包到bundle.js文件之中!
- 注意点2:
- 1:webpack默认只是处理 .js文件
- 2:非js文件,先去webpack.config.js文件中导出的的module模块中的rules规则中查找,若是存在,那么就执行,
若是不存在,那么就报错You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
appropriate loader 合适的加载器 - 3:loader调用顺序,是从后面到前面的,后面处理后,把结果返回给前面的loader,loader处理完毕后,最后一个loader会返回给webpack,让webpack拿着最终的结果,打包到bundle.js文件之中!
- 4:webpack 只关心非js文件的处理结束的结果,直接打包到bundle.js文件,不会关心第三方loader的处理过程!
处理 .css后缀名文件,需要的加载器(style-loader 和 css-loader)
- 安装:
npm i style-loader css-loader -D
- 使用:
- 在main.js文件之中引入 .css文件
import mystyle from "./css/XX.css"
- 或者这种写法
import "./css/XX.css
只是导入了样式表! 使用这种方式更好
在webpack.config.js文件中配置 .css文件 和 加载器的规则! 就是module这部分的匹配规则!const path = require("path"); //引入操作html文件 实现 const htmlWebpackPlugin = require("html-webpack-plugin") module.exports = { entry: path.join(__dirname, "./src/main.js"), output: { path: path.join(__dirname, "./dist"), filename: "bundle.js" }, //插件相关的 plugins: [ new htmlWebpackPlugin({ template: path.join(__dirname, "./src/index.html"), filename: "index.html" }) ], //配置非js文件的模块加载 loader module: { rules: [ //配置 非js文件 和 loader的对应关系! { test: /\.css$/, //匹配以.css文件结尾的文件 use: ['style-loader', 'css-loader'] //然后使用这个两个加载器去处理! } ] } }
- 在main.js文件之中引入 .css文件
处理 .less后缀名文件,需要的加载器(less-loader less)
- 注意点:就是less是 less-loader的内置依赖项,不需要配置loader规则里面!
- 安装:
npm i less-loader -D
- 引入: 在main.js文件中引入
import "./css/index.less"
- 配置: 在webpack.config.js文件中配置 => module => rules
//这边省略了 module.export = {} 和 .css配置项一样! //配置非js文件的模块加载 loader module: { rules: [ //配置 非js文件 和 loader的对应关系! { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] //匹配less,处理好后,返回给css处理,最后返回给webpack打包到 bundle.js } ] }
处理 .scss后缀名文件,需要的加载器(sass-loader node-sass)
- 安装:
cnpm i sass-loader -D
cnpm i node-sass -D
- 引入:在main.js文件中引入
import "./css/XXX.scss
处理 img文件,需要的加载器(url-loader file-loader)
- 注意点:就是file-loader是url-loader的内置项,只需要安装即可,不需要配置!
- 安装:
npm i url-loader -D
npm i file-loader -D
- 引用:
.box { width: 200px; height: 200px; background: #000 url("../images/vue之命名视图,实现同一个路径显示多个组件.png"); }
- 配置:在webpack.config.js文件中 module => rules
{ test:/\.jpn|png|gif|.webp$/,//等img的后缀名 use: ["url-loader?limit=1190&name=[name].[ext]"] //匹配 img的各种后缀 处理后打包! //limit这是给url-loader传递参数,其中有这样一个参数为limit,表示图片的大小,给定一个数值即可!(字节的单位) //如果指定了limit参数,则只有图片的大小,小于给定的值的时候,才会转为base64编码,否则就不会转换! //name=[name].[ext] => img文件打包前是什么名字还有什么后缀就是原始打包上去 //name=[hash:6][name].[ext] => 为了实现两种img不重名,出现覆盖,可以这样设置! }
处理 es6高级语法转化为es5语法,需要两套包的搭配使用
- 01:
npm i babel-core babel-loader@7 babel-plugin-transform-runtime -D
在webpack.config.js配置babel-loader,其他两个是他的内置依赖包 注意点:babel-loader@7 版本为7.X - 02:
npm i babel-preset-env babel-preset-stage-0 -D
注意点:就是以babel-preset
开头的包是Babel语法 就是以babel-plugin
开头的包是Babel插件 - 03:在webpack.config.js文件配置
{ test: /\.js$/, use: "babel-loader", exclude: /node_modules/ //添加转化js文件的loader,必须把node_modules目录下的js排除掉!这样才会忽略掉node_modules //就是匹配到这个.js文件,使用babel-loader进行转换,但是babel-loader不识别语法,因此还需要一个配置文件(识别高级语法和低级语法的字典库! => .babelrc) }
- 04:在项目根目录下,创建一个babel的配置文件 .babelrc 在里面写配置!
{ "plugins": ["transform-runtime"], "presets": ["env", "stage-0"] //语法 }
- 05:关于babel的吧ES6转化为ES5的过程
- 1:把es6拉取到babel之中,进行加工
- 2:babel-loader:只是负责进行转换,但是不知道高级语法还是低级语法
- 3:babel-preset-env 和 babel-preset-stage-0 高级语法转化为低级语法的字典库
webpack的介绍之 发布篇
1:其实在实际开发之中,webpack有着两套方案,一套关于开发时方案,一套关于发布时的方案
- 开发时的方案:这里面包含着测试文件,开发工具,测试数据等配置,有利于开发和测试,但是这些文件只是用于开发而言,发布时会剔除掉!
- 发布时的方案:剔除了那些用户用不到的测试工具和文件后,使得项目变得干净清晰,减少项目体积,有利于项目的安装和部署!
发布时的配置文件
- 1:在项目的根目录下,创建一个webpack.publish.config.js => 这是关于项目发布的配置文件!
- 2:在package.json文件配置发布时的脚本命令 => npm run pub =>执行的指令!
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --open --hot", // "pub":"webpack" //只是配置这个的话,会加载默认的配置文件 **webpack.config.js** 但是发布时,需要加载的是**webpack.publish.config.js文件**,因此需要在后面指定,需要加载的配置文件! "pub": "webpack --config webpack.publish.config.js" }
- 3:输入的时候
output: { path: path.join(__dirname, "./dist"), filename: "index.js" //修改为index.js文件! 以作区分 },
对images路径的添加前缀,存放在统一的文件夹上
- 在webpack.publish.config.js文件中的module=> rules => 的匹配img中添加
{
test: /\.jpg|png|gif|webp$/,
use: ["url-loader?limit=1190&name=images/[name].[ext]"] //匹配 img的各种后缀 处理后打包!
//limit这是给url-loader传递参数,其中有这样一个参数为limit,表示图片的大小,给定一个数值即可!(字节的单位)
//如果指定了limit参数,则只有图片的大小,小于给定的值的时候,才会转为base64编码,否则就不会转换!
},
每一次发布的时候,都把dist文件夹中的老文件清空,只打包显示最新的文件!
- 安装:
npm i clean-webpack-plugin@2 -D
- 引入后配置 在webpack.publish.config.js=> 引入和配置
const clearPlugin = require("clear-webpack-plugin)
- 配置:
plugins: [ new htmlWebpackPlugin({ template: path.join(__dirname, "./src/index.html"), filename: "index.html" }), new clearPlugin() //在这边写入每一次开发版本更新的时候,需要清除的文件, ],
对目录的分离 之webpack4.X版本的!
-
0:官网:
https://www.webpackjs.com/plugins/split-chunks-plugin/
在使用splitChunksPlugins之前,首先要知道splitChunksPlugins是webpack主模块中的一个细分模块,无需npm引入。
功能上:splitChunksPlugins只能用于如何抽离公用的代码,也就是抽离公用代码的规则,要记住,除了这个功能之外,splitChunksPlugins再无其他功能 参考:https://www.cnblogs.com/cangqinglang/p/10796534.html
0: optimization => 优化 1:splitChunks => 拆分块! 2:cacheGroups 名字叫做缓存组,其实就是存放分离代码块的规则的对象,叫做cacheGroup的原因是webpack会将规则放置在cache流中,为对应的块文件匹配对应的流,从而生成分离后的块。 cacheGroup中priority 为分离规则的优先级,优先级越高,则优先匹配。 3:vendor => 第三方目录 4.test 用于规定缓存组匹配的文件位置,test: /node_modules/ 即为匹配相应文件夹下的模块 5.name 用以控制分离后代码块的命名,当存在匹配的缓存组(后面会说到)时,命名使用缓存组中的name值,若不存在则为 [来源]~[入口的key值].js 的 格式 6.chunks 匹配的块的类型:initial(初始块),async(按需加载的异步块),all(所有块) 7. minSize 分离后的最小块文件大小,单位为字节 8. minChunks 分离前,该块被引入的次数(也就是某个js文件通过import或require引入的次数)
-
1:开发的代码:打包保存在dist目录
-
2:第三方插件:打包到vendors目录(也就是第三方包的名称)
- 因此需要对webpack.publish.config.js文件修改入口文件和输出文件
- 导入webpack包
const webpack = require("webpack");
- 引入清除每一次发布前的dist目录
const clearPlugin = require("clean-webpack-plugin")
- 把模块的入口文件修改为app和vendors,就是项目主文件和下面第三方包
entry: { app: path.join(__dirname, "./src/main.js"), //这是项目的主文件 }
- 把公共的部分抽离出来(比如jq啊) => 使用optimization的配置项来配置(注意点:这个配置项和entry,output同级别!)
optimization: {//优化 splitChunks: {//分割快 cacheGroups: {//缓冲组 commons: { name: "vendors",//打包后的名称 chunks: "initial", minChunks: 1, } } } }
- 导入webpack包
- 因此需要对webpack.publish.config.js文件修改入口文件和输出文件
最终相关代码
//导入webpack包
const webpack = require("webpack");
//引入,清除发布时的文件
const clearPlugin = require("clean-webpack-plugin")
module.exports = {
entry: {
app: path.join(__dirname, "./src/main.js"), //这是项目的主文件
},
output: {
path: path.join(__dirname, "./dist"),
filename: '[name].js' //也可以在这边设置目录 'js/[name].js' => 这个name拿到之前的name,不修改名!
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: "vendors",
chunks: "initial",
minChunks: 1,
}
}
}
},
..... 中间 ...
}
webpack之压缩 和 转化
webpack之压缩js
-
官网:
https://webpack.docschina.org/plugins/uglifyjs-webpack-plugin/#root
选择uglifyOptions => 移除警告灯信息
选择Options => 进行相关的配置! -
安装:
npm install uglifyjs-webpack-plugin --save-dev
-
引入: 在webpack.publish.config.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
-
配置项的解析:
1:optimization => 优化 2:minimizer => 最小值 (也就是压缩)
-
使用:optimization=>minimizer最小值!
-
使用DefinePlugin插件,实现对第三方包的优化
-
官网:
https://webpack.docschina.org/plugins/define-plugin/
new webpack.DefinePlugin({ //本插件的作用:就是在全局作用域下配置的全局变量,为了给第三方插件使用的, // 比如vue,还会检查webpack检查这个字段PRODUCTION,为发布环境阶段,那么会移除掉警告,并且做优化! PRODUCTION: JSON.stringify(true), "myVar": "'123'" }),
webpack4之css,less,scss抽离与压缩
抽离 mini-css-extract-plugin
- 官网:
https://webpack.docschina.org/plugins/mini-css-extract-plugin/#root
- 安装:
npm install --save-dev mini-css-extract-plugin
- 引入:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
- 使用:使得css不会被压在到index.js,抽离到一个样式表之中!
module.exports = { new MiniCssExtractPlugin({ filename: 'css/[name].css', }), module: { rules: [ { test: /\.css$/i, use: [{ loader: MiniCssExtractPlugin.loader, options: { publicPath: '../', //公共的路径,为了在dist中的index.html能使用到这些css等! }, }, 'css-loader', ], }, { test: /\.less$/i, // 这是对于less和scss的提取 还是需要定义在一个匹配对象上的,为了方便就跳过了! use: [ .... 类似上面的css, 'css-loader', 'less-loader'], use: [ .... 类似上面的css, 'css-loader', 'sass-loader'], }, ], }, };
压缩 optimize-css-assets-webpack-plugin
- 安装:
npm i optimize-css-assets-webpack-plugin -D
- 引入:
//普通压缩 plugins: [ new OptimizeCSSAssetsPlugin () ] // 使用cssnano配置规则 // 先 npm i cssnano -D plugins: [ new OptimizeCSSAssetsPlugin ({ // 默认是全部的CSS都压缩,该字段可以指定某些要处理的文件 assetNameRegExp: /\.(sa|sc|c)ss$/g, // 指定一个优化css的处理器,默认cssnano cssProcessor: require('cssnano'), cssProcessorPluginOptions: { preset: [ 'default', { discardComments: { removeAll: true}, //对注释的处理 normalizeUnicode: false // 建议false,否则在使用unicode-range的时候会产生乱码 }] }, canPrint: true // 是否打印编译过程中的日志 }) ]
压缩之html文件的压缩
- 安装:
- 引入:
- 配置:
new htmlWebpackPlugin({
template: path.join(__dirname, "./src/index.html"),
filename: "index.html",
minify: { //表示提供压缩选项
removeComments: true, //移除页面的注释
collapseWhitespace: true, //合并空白字符
removeAttributeQuotes: true, //移除属性节点上的引号!
}
}),