webpack的几个核心属性
一、entry
指定入口文件,webpack将根据入口文件来建立依赖关系从而进行打包构建
entry分为单入口和多入口
单入口
entry: "./src/main.js",
多入口则以对象的形式
entry:{
index:"./src/main.js",
util:"./src/util/index.js",
...
}
二、output
打包后的输出
output: {
//所有文件的输出路径,__dirname: nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "dist"),//绝对路径
//最终产物的文件名,可以指定 也可以使用[name]占位 这样的话就会使用入口文件的名字,多入口的时候必须以占位的形式
filename: "bundle.js",
//代码块的文件名
chunkFilename:"[name].chunk.js",
clean:true //自动删除上次打包的结果
},
三、loader
webpack原生只支持解析js和json文件,而在我们日常开发中除了这两种文件还有其他的如 css less scss vue ts jsx 图片 音视频等等种类的文件,loader就是用来解析这类文件将他们转成webpack可解析的格式。loader是一个函数 接收源文件为参数 最终输出一个webpack认识的东西。
下面是一些常见的loader
webpack本身是单线程的模式去打包构建的 thread-loader可以让webpack多进程打包 从而加快打包速度
loader语法
module: {
rules: [
//rules是一个数组里面可以配置多个loader,每个对象表示对一个loader的描述
{
//当前loader对哪些文件生效 ,是一个正则匹配规则
test:'',
use:[]
//use里可以放置多个loader,
//执行顺序:从右到左或者从下到上,最末尾的loader最先执行
}
]
}
四、Plugins
字面意思就是插件。通常一些loader没办法完成的事情都可以通过插件来完成,他主要用于对构建产物的优化,资源管理以及环境变量的注入。
注:在整个构建环节都可以去使用plugins,他作用于整个构建过程,webpack会在构建过程中不停的去广播一些事件,而plugins可以监听这些事件 从而进行相对应的处理
一些常见的plugins
五、mode
webpack构建模式,有三个可选值
development,production,none
设置不同的模式webpack会为你默认启动一些优化选项
了解完了以上几个webpack的关键点之后 让我们来做个小小的练习吧。
打包构建一个vue应用。
基本配置
首先分析一下想要打包vue文件肯定是需要能够解析vue的loader的,这里vue官方就给我们提供了这样一个loader vue-loader,下面是官方文档
https://vue-loader.vuejs.org/zh/guide/#vue-cli
根据官网的教程,可以得到以下的基本配置
const path = require('path');//nodejs的核心模块,专门用来处理路径问题
const {VueLoaderPlugin} = require("vue-loader");
module.exports = {
//入口
entry: "./src/main.js",//相对路劲
//输出
output: {
//所有文件的输出路径
//__dirname: nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "dist"),//绝对路径
//最终产物的文件名,可以指定 也可以使用[name]占位 这样的话就会使用入口文件的名字,多入口的时候必须以占位的形式
filename: "bundle.js",
//代码块的文件名
// chunkFilename:"[name].chunk.js",
clean:true //自动删除上次打包的结果
},
//加载器
module: {
rules: [
//loader的配置
{//通过babel-loader解析es6es7语法转为es5
test:/\.js$/,
use:[
"babel-loader"
]
},
{
//通过vue-loader解析vue文件
test:/\.vue$/,
use:[
"vue-loader"
]
},
]
},
//插件
plugins: [
//plugin的配置
new VueLoaderPlugin()
],
//模式
mode: "development",
// devtool: "source-map"//输出源代码
}
要注意可不是只用上一个vue-loader就行了哦,还需要配合VueLoaderPlugin插件才能完成对vue文件的打包。
接下来我们准备一个入口文件以及一个vue文件作为跟组件。
//main.js
import Home from './vue/Home.vue'
import {createApp} from 'vue'
console.log(createApp,Home,123)
const app = createApp(Home).mount('#app')
console.log(app)
//Home.vue
<template>
<div>{{msg}}</div>
</template>
<script>
import {ref} from "vue";
export default {
name: "Home",
setup(){
const msg = ref('Home test')
return{
msg
}
}
}
</script>
<style scoped>
</style>
最后在准备一个html文件引入我们打包后的js文件即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>hello webpack</div>
<div id="app"></div>
<script src="../dist/bundle.js"></script>
</body>
</html>
注意引入的js的文件要么异步加载要么放在跟标签后面,不然就会出现vue找不到跟标签挂在元素了
这样就完成了一个简单的编译打包vue文件的过程。
下面看看webpack是如何解析css和字体图片文件的
首先 解析css 需要用到两个loader,一个是css-loader用来将css资源编译成common.js的模块到js中,第二个 style-loader将js中的css通过创建style标签的形式添加到html中,以生效
{
test: /\.css$/, //只检测.css文件
use: [ //执行顺序:从右到左或者从下到上,最末尾的loader最先执行
"style-loader",//将js中的css通过创建style标签的形式添加到html中,以生效
"css-loader", //将css资源编译成common.js的模块到js中
]
},
这样就可以完成对css的解析。
打包图片资源和字体资源
使用到file-loader或者url-loader
//打包图片资源
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
use:[
{
loader: "url-loader",
options: {
limit:10*1024
}
}
]
},
这里使用了url-loader,因为url-loader可以配置将小于多少大小的文件打包成base64,其内部也是使用的file-loader,只不过功能做了一些扩展。
PS:base64格式有利于减少http请求,但是如果文件过大 生成的base64也会特别大。所以只适合让小文件转成base64格式
接下来去学习webpack中的文件监听。
webpack提供了一个watch属性当他为true的时候 文件改变就会自动触发webpack的重新构建,这和我们日常开发中的热更新不同,他只是重新生成了构建产物 但是并不会触发浏览器的刷新,所以还需要我们手动刷新浏览器。
也可以在webpack运行命令后面加上--watch开启监听模式
"watch-build": "npx webpack --watch"
这样执行这个命令就可以开启监听模式
原理分析
讲到了文件监听那就不得不提webpack的热更新了。热更新需要用到两个包
webpack-dev-server和hot-module-replacement-plugin
以下简称WDS和HMR
热更新的原理就是通过WDS启动一个本地服务器,此时构建出的东西就不会输出实际的文件了 而是会被放到本地的服务器上。然后HMR会在bundle里注入一个HMR runtime,这个东西是存在于浏览器端的,他会和WDS建立一个scoket连接。当有文件被修改的时候会再次经过webpack编译,webpack编译后就会将最新的代码发送至本地服务器上,本地服务器就会通知runtime runtime再去修改局部的变更。(PS:所以我们在开发项目式 run dev是看不到dist文件夹的,如果想查看run dev生成了什么东西可以在本地服务端口后面拼上webpack-dev-server即可)。
文件指纹
在webpack中所谓的文件指纹其实就是指打包生成的文件名后的hash值。那这个哈希值有什么用呢。在每次构建项目的时候可能只是改动了一两个文件,如果文件名不发生变化,那在浏览器上是会被缓存下来的,所以用户没办法第一时间看到更新之后的资源。而如果我们给发生了变化的文件加上新的哈希值,浏览器就会去下载最新的。而那些没发生变化的则继续沿用缓存里的。这样可以极大的利用浏览器缓存。
webpack里得哈希大概分为以上两种,一般我们打包静态文件会选择Hash 而js则会选择Chunkhash,css则是Contenthash。
用法也很简单,直接在输出得文件名里使用占位符即可。
output: {
//所有文件的输出路径
//__dirname: nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "dist"),//绝对路径
//最终产物的文件名,可以指定 也可以使用[name]占位 这样的话就会使用入口文件的名字,多入口的时候必须以占位的形式
filename: "[name]_[chunkhash:8].js", 这里我们只取前八位就行,默认是32位
//代码块的文件名
// chunkFilename:"[name].chunk.js",
clean:true //自动删除上次打包的结果
},
之前我们得css都是通过style-loader以style标签得形式插入html,要使用哈希得话我们就得借助另一个loader,让css以link标签得方式引入。
npm install --save-dev mini-css-extract-plugin
插件文档:https://webpack.docschina.org/plugins/mini-css-extract-plugin/
具体使用方法看文档即可
//使用此插件将css分离出文件通过link引入
new MiniCssExtractPlugin({
filename:'[name]_[contenthash:8].css'
})
代码压缩
webpack是自带了js代码压缩的,所以下面主要介绍一下css的压缩和html的压缩
css的压缩主要用到的插件有optimize-css-assets-webpack-plugin以及CssMinimizerPlugin
两者都是依赖于cssnano的,所以要先安装一下cssnano。
使用方法也很简单,在plugins里new一下就行。
html的压缩需要借助HtmlWebpackPlugin,配置一下minify对象即可
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'public/index.html',
inject: true,//配置所有js资源放置在html得哪个位置
minify:{
//压缩配置
collapseWhitespace: true,
preserveLineBreaks:false,
html5:true,
minifyCSS:true,
minifyJS:true,
removeComments: true,
}
}),
以上就是webpack的基础入门了