什么是Webpack
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
为什要使用WebPack
- 现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法
模块化,让我们可以把复杂的程序细化为小的文件; - 类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能 够实现目前版本的JavaScript不能直接使用的特性,并且之后还能能装换为JavaScript文件使浏览器可以识别;
- Scss,less等CSS预处理器…
- 这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常反锁的,这就为WebPack类的工具的出现提供了需求。
webpack打包原理
把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载。
webpack的优势
(1) webpack 是以 commonJS 的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
(2)能被模块化的不仅仅是 JS 了。
(3) 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。
(4)扩展性强,插件机制完善
什么是loader,什么是plugin
loader用于加载某些资源文件。因为webpack本身只能打包common.js规范的js文件,对于其他资源如css,img等,是没有办法加载的,这时就需要对应的loader将资源转化,从而进行加载。
plugin用于扩展webpack的功能。不同于loader,plugin的功能更加丰富,比如压缩打包,优化,不只局限于资源的加载。
什么是bundle,什么是chunk,什么是module
bundle: 是由webpack打包出来的文件
chunk: 是指webpack在进行模块依赖分析的时候,代码分割出来的代码块
module: 是开发中的单个模块
webpack 和 gulp 的区别?
webpack:
gulp是一个前端自动化构建工具,强调的是前端开发的工作流程,可以通过配置一系列的task,第一task处理的事情(如代码压缩,合并,编译以及浏览器实时更新等)。然后定义这些执行顺序,来让glup执行这些task,从而构建项目的整个开发流程。自动化构建工具并不能把所有的模块打包到一起,也不能构建不同模块之间的依赖关系。
什么是模热更新?有什么优点?
模块热更新是webpack的一个功能,它可以使得代码修改之后,不用刷新浏览器就可以更新。在应用过程中替换添加删出模块,无需重新加载整个页面,是高级版的自动刷新浏览器。
优点:
只更新变更内容,以节省宝贵的开发时间。调整样式更加快速,几乎相当于在浏览器中更改样式
webpack-dev-server 和 http服务器的区别
webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,比传统的http服务对开发更加有效
什么是长缓存?在webpack中如何做到长缓存优化?
浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式就是引入新的文件名称。
在webpack中,可以在output给出输出的文件制定chunkhash,并且分离经常更新的代码和框架代码,通过NameModulesPlugin或者HashedModulesPlugin使再次打包文件名不变。
什么是Tree-sharking?CSS可以Tree-shaking吗?
Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。在webpack中Tree-shaking是通过uglifySPlugin来Tree-shakingJS。Css需要使用Purify-CSS。
如何可以自动生成webpack配置?
npm i webpack webpack-cli -D
在项目中配置webpack
在项目根录中,创建名为webpack.config.js 的webpack配置文件,并初始化如下的基本配置
在package.json的script节点下,新增serve脚本如下:
mode 节点 的可选值有两个,分别是:
development
- 开发环境
- 不会对打包生成的文件进行代码压缩和性能优化
- 打包 速度快 ,适合在 开发阶段使用 production
- 生产环境
- 会对打包生成的文件进行代码压缩和性能优化
- 打包 速度很慢 ,仅适合在项目 发布阶段 发布阶段 使用
webpack的插件
html-webpack-plugin
- webpack中的 HTML 插件(类似于一个模板引擎)
- 可以通过此插件自定制 index.html页面的内容
- webpack-dev-server 可以让 webpack 监听项目源代码的变化 ,从而进行自动打包构建 。
安装 webpack-dev-server
配置 webpack-dev-server
- 修改 package.json -> scripts 中的 serve 命令如下:
##### 打包处理 css 文件 - 运行 npm i style-loader css-loader -D 命令,安装处理 css 文件的 loader
- 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如
##### 打包处理样式表中与 url 路径(图片)相关的文件 - 运行 npm i url-loader file-loader -D 命令
- 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
自动清理 dist 目录下的旧文件
为了在每次打包发布时自动清理掉 dist 目录中的旧文件,可以安装并配置 clean-webpack-plugin 插件:
现在项目终端中运行如下命令
-
npm i clean-webpack-plugin -D
-
配置clean-webpack-plugi
//导入htmL-webpack-plugin插件处理htmL目标
//提前安装 npm i htmL-webpack-plugin -D
//npm i clean-webpack-plugin -D
//作用:清零dist目录(执行npm run build需要清理上一次的生成的内容)
const {CleanWebpackPlugin} = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
//自定拷贝到dist目录,插入打包好的js文件
//使用loader
//npm i css-loader style-loader -D
// css-loader处理css文件,style-loader把加载好的css放入style标签
module.exports = {
entry: './src/index.js', //入口
output: { //出口
filename: "main.js", //文件名
path: __dirname + '/dist', //文件夹 dirname当前归录
},
mode: "production", // // 模式 development开发模式 production 产品模式
plugins: [
//实例化插件,指定tempLate模板的位置
new HtmlWebpackPlugin({
template: './public/index.html'
}),
//实例化清理
new CleanWebpackPlugin()
],
module: {
rules: [
//当文件名test通过,使用如下插件
{ test: /\.css$/, use: ["style-loader", "css-loader"] },
// 需要提前安装url-loader file-loader
{test:/\.(png|jpg|jpeg|webp|ico|gif|bmp)$/,
use:[{
loader:"url-loader", //使用url加载器
options:{limit:5000,name:'images/[hash].[ext]'},
//选项,当图片小于5000字节时候,转换base64(小图片减少一次http请求)
//文件命名images文件夹,hash值(计算出图片的名称)ext后缀名
}]
},
]
},
//需要提前安装npm i webpack-dev-server -D
devServer: {
port: 8080,
hot: true,//更新
host: "localhost",//域名
open: true,//默认自动打开浏览器
proxy: {} //vue.config.js代理一致
}
}
// module 模块 exports 导出 entry output 输出 filename 文件名 path 路径 dirname 当前目录 dist 目标
// module 模式 deveLopment 开发模式 production 产品
//dev开发Server服务器prot端口号hot热更新 host域名 open打开 proxy代理
配置 webpack 的打包发布
"scripts": {
"build": "webpack",
"serve": "webpack serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
打包处理样式表中与 url 路径(图片)相关的文件
- 运行 npm i url-loader file-loader -D 命令
- 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
- 处理文件(图片,文件)
- 安装: npm i file-loader url-loader -D
- 处理文件(图片,文件)
const HtmlWebpackPlugin = require("html-webpack-plugin")
//自定拷贝到dist目录,插入打包好的js文件
module.exports = {
entry: './src/index.js', //入口
output: { //出口
filename: "main.js", //文件名
path: __dirname + '/dist', //文件夹 dirname当前归录
},
mode: "production", // // 模式 development开发模式 production 产品模式
plugins: [
//实例化插件,指定tempLate模板的位置
new HtmlWebpackPlugin({
template: './public/index.html'
}),
],
module: {
rules: [
// 需要提前安装url-loader file-loader
{test:/\.(png|jpg|jpeg|webp|ico|gif|bmp)$/,
use:[{
loader:"url-loader", //使用url加载器
options:{limit:5000,name:'images/[hash].[ext]'},
//选项,当图片小于5000字节时候,转换base64(小图片减少一次http请求)
//文件命名images文件夹,hash值(计算出图片的名称)ext后缀名
}]
},
]
},
}
处理sass
- 安装: npm i sass sass-loader -D
- 处理scss文件
- {test:/.scss$/,use:[“style-loader”,“css-loader”,“sass-loader”]}
- 配置clean-webpack-plugi
- {test:/.scss$/,use:[“style-loader”,“css-loader”,“sass-loader”]}
//导入htmL-webpack-plugin插件处理htmL目标
//提前安装 npm i htmL-webpack-plugin -D
//npm i clean-webpack-plugin -D
//作用:清零dist目录(执行npm run build需要清理上一次的生成的内容)
const {CleanWebpackPlugin} = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
//自定拷贝到dist目录,插入打包好的js文件
//使用loader
//npm i css-loader style-loader -D
// css-loader处理css文件,style-loader把加载好的css放入style标签
module.exports = {
entry: './src/index.js', //入口
output: { //出口
filename: "main.js", //文件名
path: __dirname + '/dist', //文件夹 dirname当前归录
},
mode: "production", // // 模式 development开发模式 production 产品模式
plugins: [
//实例化插件,指定tempLate模板的位置
new HtmlWebpackPlugin({
template: './public/index.html'
}),
//实例化清理
new CleanWebpackPlugin()
],
module: {
rules: [
//当文件名test通过,使用如下插件
{ test: /\.css$/, use: ["style-loader", "css-loader"] },
// 需要提前安装url-loader file-loader
{test:/\.(png|jpg|jpeg|webp|ico|gif|bmp)$/,
use:[{
loader:"url-loader", //使用url加载器
options:{limit:5000,name:'images/[hash].[ext]'},
//选项,当图片小于5000字节时候,转换base64(小图片减少一次http请求)
//文件命名images文件夹,hash值(计算出图片的名称)ext后缀名
}]
},
]
},
//需要提前安装npm i webpack-dev-server -D
devServer: {
port: 8080,
hot: true,//更新
host: "localhost",//域名
open: true,//默认自动打开浏览器
proxy: {} //vue.config.js代理一致
}
}
// module 模块 exports 导出 entry output 输出 filename 文件名 path 路径 dirname 当前目录 dist 目标
// module 模式 deveLopment 开发模式 production 产品
//dev开发Server服务器prot端口号hot热更新 host域名 open打开 proxy代理
抽出插件
- 安装: npm i mini-css-extract-plugin -D
- 作用:把css抽出为一个单独的文件
- 导入: const MiniCssExtractPlugin = require(“mini-css-extract-plugin”)
- 配置loader
{test:/.css$/,use:[MiniCssExtractPlugin.loader,“css-loader”]} - 实例化插件
new MiniCssExtractPlugin()
// 导入css 抽出插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module:{
rules:[
// 当文件名test通过,使用如下插件
{test:/\.css$/,use:[/*"style-loader",*/ MiniCssExtractPlugin.loader,"css-loader"]},
]
},
plugins:[
// 实例化插件
new MiniCssExtractPlugin()
]
优化
- css 压缩
- 安装:npm i css-minimizer-webpack-plugin -D
- 导入:const CssMinimizerPlugin = require(“css-minimizer-webpack-plugin”);
- js的压缩
- 安装:npm i terser-webpack-plugin -D
- 导入:const TerserPlugin = require(“terser-webpack-plugin”);
- 实现压缩与优化
optimization: { minimize: true, //默认是压缩 minimizer: [new CssMinimizerPlugin(),new TerserPlugin()],//压缩器 }, - 代码分割
optimization: { splitChunks: { chunks: “all”, // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件}, }
// 导入css优化插件
// 需要安装:css-minimizer-webpack-plugin
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// js压缩
// 需要安装 npm i terser-webpack-plugin -D
const TerserPlugin = require("terser-webpack-plugin");
//导入vue-loader
const {VueLoaderPlugin} = require("vue-loader")
module.exports = {
optimization: { //优化选项
// minimize: true, //默认是压缩
minimizer: [new CssMinimizerPlugin(),new TerserPlugin()],//压缩器
splitChunks: { // 代码分割 当js比较小会多个合成1个,当js超过3m一个分割为多个
chunks: "all",
}
},
// js经过了压缩,如果出错了,找错误困难,
// js出的错误和源代码有个一一对应关系
特殊标识
- 目录别名
resolve: {
// 别名:@代表是 src目录
alias: {
'@': path.resolve(__dirname, './src'), //设置@为src目录的别名
}
},
v开发工具
devtool:“eval-cheap-source-map”
配置 webpack 的打包发布
- 在 package.json 文件的 scripts 节点下,新增 build 命令如下:
"scripts": {
"build": "webpack",
"serve": "webpack serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
link与script
- < script defer src=“”> < /script>等待页面内容加载好再去加载js
- < link href= “” rel=prefetch>提前预加载css
webpack中的魔法注释
- 魔法注释
import(/* webpackChunkName:"jquery" , webpackPrefetch: true */ "jquery").then(({default:$})=>{
console.log($);
})
/* webpackChunkName:"jquery" 给当前的js 文件命名 */
/* webpackPrefetch: true 网络有空闲预加载js */
哈希命名
- 可以控制浏览器的缓存
当文件发生变化时候,hash就变化,文件名也就变化,浏览器就不缓存
当文件名保持不变,浏览器二次请求会从缓存里面去请求内容 - 提供二次加载的速度(有效的控制缓存)
contenthash 内容发生变化 contenthash值才发送变化
chunkhash入口发生变化,当前的文件chunkhashhash会变化
hash只要项目内容发送变化,hash就会变化
output:{ //出口
filename:"[name]-[chunkhash].js",//文件名
// path:path.resolve(__dirname,'/dist')
path:__dirname+'/dist' //文件夹 __dirname 当前目录
},
// 初始化css抽出插件
new MiniCssExtractPlugin({
filename:"style-[contenthash].css"
}),
options:{limit:5000,name:'images/[hash].[ext]'},
环境变量
- 配置:通过环境命令 产品环境 压缩代码,是生产环境不压缩代码,打开devtool
- 项目开发中 ,产品环境 baseURL http://dida100.com:8888
- 生产环境 baseURL http://localhost:8080
- .npm i cross-env -D
- package.json 传参
"build": "cross-env NODE_ENV=production webpack",
"serve": "cross-env NODE_ENV=development webpack serve",
- js文件中使用
var baseURL = "";
if(process.env.NODE_ENV=="production"){
baseURL = "http://dida100.com";
}else{
baseURL = "http://localhost"
}
console.log("当前环境:",process.env.NODE_ENV,baseURL);
vue脚手架
-
不要vue脚手架如何搭建项目?
安装
npm i vue -S
npm i
vue-loader 处理.vue
vue-template-compiler编译vue目录
vue-hot-reload-api热更新
vue-style-loader 处理vue 样式
-D -
配置
01 导入
const {VueLoaderPlugin} = require(“vue-loader”)
02 配置
{test:/.vue$/,use:[“vue-loader”]}
03 插件
plugins:[new VueLoaderPlugin()] -
js
- 模板文件 public/main.html写入
< div id=“app”>< /div> - src/main.js中写入
- 模板文件 public/main.html写入
//导入创建app的方法
import {createApp} from 'vue';
//导入App.vue
import App from './App.vue'
console.log(App);
//创建App并挂载
createApp(App).mount("#app")
App.vue中写入
<template>
<div>
<h1>你好vue</h1>
<p>{{msg}}</p>
<input type="text" v-model="msg">
<button @click="num++">{{num}}</button>
</div>
</template>
<script>
export default {
data () {
return {
msg:'你好,四川!',
num:5
}
},
}
</script>