webpack功能
1. 配置全局變量
使用webpack自帶的 providePlugin, 可以配置全局變量.
{
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: "jquery",
})
]
}
2. 多入口打包
多入口打包,就是打包的文件, 不止有index.html一個(gè)入口,而是多個(gè). 比如login.html.那么就需要
- 在plugins中用
HtmlWebpackPlugin創(chuàng)建多個(gè)入口 - 打包的js文件也不能打包在一個(gè)文件中, 一個(gè)入口的文件,不需要其他入口文件打代碼.所以在entry里配置多個(gè)入口
- 在 HtmlWebpackPlugin的chunks里配置入口html文件要加載的js模塊.
module.exports = {
mode: 'development',
entry: {
// 多入口打包
index: "./src/index.js",
login: "./src/login.js",
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 最后再dist里生成的入口文件, 如果寫(xiě) a.html的話, 在dist里就不是index.html, 而是a.html了
template: './src/index.html',
// 當(dāng)前打包入口 加載的js模塊, 這里的模塊名是 entry里面的key對(duì)應(yīng)的模塊
chunks: ['index'],
}),
new HtmlWebpackPlugin({
filename: 'login.html',
template: './src/login.html',
chunks: ['login'],
}),
]
}
3. 圖片打包
webpack自帶文件處理插件. 用type: 'asset',配置.
{
module: {
rules: [
{
test: /\.(png|jpg|jpeg|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 1 * 1024,
}
},
generator: {
// 圖片文件都 創(chuàng)建到 img文件夾下, 名稱(chēng)格式: 原名.6位hash.圖片后綴.
// 帶hash是為了防止不同文件夾下面有同名文件.現(xiàn)在放到 img文件夾下面了.為了區(qū)分加個(gè)hash
filename: 'img/[name].[hash:6][ext]',
}
}
]
},
}
4. 開(kāi)發(fā)模式的本地服務(wù)器.
這里的文檔我看了, 可以看懂
在有dev-server之前的開(kāi)發(fā)情況
- 在源文件修改后, 執(zhí)行npm run build, 打包生成dist打包文件.
- 在dist/index.html用"open with live server"打開(kāi), 查看修改內(nèi)容
問(wèn)題: - 每一次修改都得手動(dòng)build一下, 才能看到, 非常麻煩.
解決方案: - 用webpack-dev-server開(kāi)啟一個(gè)服務(wù)器, 針對(duì)src里的源文件做監(jiān)控, 當(dāng)文件變化后, 自動(dòng)build打包成dist. 然后用服務(wù)器打開(kāi)dist/index.html.
webpack-dev-server實(shí)際上是, 把開(kāi)發(fā)代碼,打包到dist,
然后在dist目錄中, 以dist為根目錄,啟動(dòng)服務(wù)器, 打開(kāi)了index.html文件.
實(shí)際效果跟在vscode中, 右鍵點(diǎn)擊dist/index.html,選擇 open with live server 是一樣的.
所謂的開(kāi)發(fā)模式, 就是
- 以dist為根目錄,啟動(dòng)服務(wù)器, 打開(kāi)dist/index.html文件.
- 當(dāng)源碼文件有變化時(shí),就打包一次. 更新dist里的文件代碼
- hot熱更新模式,就是當(dāng)監(jiān)控到文件變化時(shí), 主動(dòng)更新瀏覽器.刷新瀏覽器,或dom結(jié)構(gòu).
- 關(guān)于圖片文件.在源碼中路徑是
./img/login/icon.png,由于打包后統(tǒng)一放到了dist/img下面, 所以應(yīng)該是看不到圖片的,此時(shí)圖片的真實(shí)地址是http://localhost:9080/img/19.77aff4.jpg - 為了解決問(wèn)題4, 使用了
CopyWebpackPlugin,該插件會(huì)把圖片的完整路徑,復(fù)制一份到dist下面,
這樣dev-server就能找打?qū)?yīng)的文件了. 同時(shí)這份文件只是為了開(kāi)發(fā), 所以只存在于內(nèi)存中. 實(shí)際在dist下面看不到. - 到最后,不是開(kāi)發(fā)命令而是 在執(zhí)行打包命令時(shí), 因?yàn)閷?shí)際的圖片都打包在
dist/img里, 所以后面會(huì)在打包時(shí),把所有的引入img的路徑,改成從dist/img里面拿圖片.
備注:
- copy-webpack-plugin的文檔 https://www.webpackjs.com/plugins/copy-webpack-plugin/
- dev-server的文檔 https://www.webpackjs.com/configuration/dev-server/#devserver
{
devServe:{
// 打包文件路徑
static: './dist',
server: 'http', // 啟動(dòng)的服務(wù)式http
port: 9080, // 端口好
https: false, // 是否使用https
hot: true, // 熱更新
open: true, // 是否自動(dòng)打開(kāi)瀏覽器
proxy: { // 代理
'/api': 'http://localhost:3000',
},
watchFiles: ['src/**/*.php', 'public/**/*'], // 監(jiān)聽(tīng)文件變化范圍.
webSocketServer: 'ws', //使用web-socket服務(wù)器
},
plugins: [
// 復(fù)制開(kāi)發(fā)文件到, 打包文件的插件.
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, './src/img'),
to: path.resolve(__dirname, './dist/img'),
}
]
})
]
}
5. css抽離
使用style-loader, css-loader的問(wèn)題
- 當(dāng)前對(duì)css的處理是在用
css-loader獲取到css文件后, 用style-loader,創(chuàng)建一個(gè)函數(shù), 函數(shù)效果是 直接在html上插入一個(gè)style標(biāo)簽. 把css內(nèi)容寫(xiě)入這個(gè)style標(biāo)簽里. - 這個(gè)函數(shù)會(huì)被打包到index.js里, 在index.html啟動(dòng)后執(zhí)行.
- 這樣的話, 所有的css文件都會(huì)在index.js里.會(huì)使index.js過(guò)于膨脹.也不方便對(duì)css進(jìn)行壓縮. 不符合我們對(duì)js分門(mén)別類(lèi)的需求.
- 所以我們打算把所有的css文件都打包到一個(gè)css文件夾中.
使用MiniCssExtractPlugin把css單獨(dú)打包. 把css從index.js文件沖抽離出來(lái).
- npm install --save-dev mini-css-extract-plugin
- 使用miniCss自帶的
MiniCssExtractPlugin.loader,代替style-loader獲取css內(nèi)容 - 在plugins里配置.css文件打包的路徑.
效果:
未抽離css時(shí), login.js為: 9.2kb. 抽離后變成了 login.js: 3.1kb, login.css: 5.9kb.
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
// 使用minicss的loader獲取到css的內(nèi)容chunk
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
// 把css內(nèi)容打包到 dist/css下.
new MiniCssExtractPlugin({
filename: 'css/[name].[hash:6].css',
chunkFilename: 'css/[name].css',
})
],
};
備注: https://www.webpackjs.com/plugins/mini-css-extract-plugin/
6. js代碼壓縮
問(wèn)題: 打包后的js文件太大.
解決方案: js壓縮
npm install terser-webpack-plugin --save-dev
treeshaking, lodash-es替換lodash
7. css,js代碼壓縮
問(wèn)題: 打包后的文件太大.
解決方案:
- css壓縮, 使用
CssMinimizerWebpackPlugin壓縮css, - 使用
terser-webpack-plugin壓縮js. 注意視頻里說(shuō)用uglifyjs-webpack-plugin,但是這個(gè)插件式webpack4版本的, webpack5已經(jīng)沒(méi)有了, 應(yīng)該是版本更新去掉了. 到webpack的插件列表里找,找到了替代品terser-webpack-plugin.
const MiniCssExtractPlugin = require("mini-css-extract-plugin") // css解析插件
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // css壓縮插件
{
// 優(yōu)化配置項(xiàng)
optimization: {
minimize: true, // 是否壓縮
minimizer: [
//js壓縮插件
new TerserPlugin({}),
//css壓縮插件
new CssMinimizerPlugin(),
]
},
module: {
rules: [
{
test: /\.css$/,
use: [
// css解析器用 MiniCssExtractPlugin.loader
MiniCssExtractPlugin.loader,
'css-loader',
]
},
]
}
}
8. treeshaking 不打包未使用的函數(shù)
tree,樹(shù), shaking搖動(dòng), treeshaking搖動(dòng)樹(shù)木, 把不用的葉子搖晃下來(lái). 意為打包時(shí)不打包沒(méi)有使用過(guò)的函數(shù)代碼
以lodash為例
- 比如只使用了
lodash里面的deepClone函數(shù), 但卻打包了lodash的所有的代碼. 這肯定是不劃算的. 如果是把deepClone打包進(jìn)入,不打包lodash的其他代碼.就很好的壓縮了文件大小.這就是treeshaking. - 不加lodash,打包后的index.js有
167kb - 使用
import _ from 'lodash'的方式使用_.get的index.js有279kb - 使用treeShaking方式使用get函數(shù)的index.js有
170kb,可見(jiàn)treeShaking有多么必要
使用treeshaking有幾個(gè)條件
- 用解構(gòu)方式獲取函數(shù)
import { get } from 'lodash' lodash必須符合esModule規(guī)范. 也就是用如下方式導(dǎo)出函數(shù). 不能用module.export.
export function get() {
...
}
// 這是lodash的lodash.js的函數(shù)導(dǎo)出方式. 定義了一個(gè)lodash對(duì)象. 然后在lodash對(duì)象上加各種函數(shù),再把lodash對(duì)象導(dǎo)出.
lodash.add = add;
lodash.attempt = attempt;
lodash.camelCase = camelCase;
lodash.capitalize = capitalize;
lodash.ceil = ceil;
lodash.clamp = clamp;
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash不符合esModule規(guī)范,所以treeShaking不生效. 要使用符合esModule規(guī)范的lodash-es才行.
import { get } from 'lodash-es';
- 即使函數(shù)都在同一個(gè)文件,也可以被treeshaking去掉, 條件是 webpack.config.js里的配置的mode改成生產(chǎn)模式.
mode=production - 一定要用解構(gòu)賦值來(lái)獲取函數(shù), 這樣就可以保證工具函數(shù)是esModule的寫(xiě)法(因?yàn)閷?dǎo)出對(duì)象的方式?jīng)]法用解構(gòu)來(lái)獲取函數(shù).),
export function get(){}
import { get } from 'tools';
// lodash-es的lodash.js文件的導(dǎo)出方式., 直接用export把各個(gè)函數(shù)導(dǎo)出.
export { default as add } from './add.js';
export { default as after } from './after.js';
export { default as ary } from './ary.js';
export { default as assign } from './assign.js';
export { default as assignIn } from './assignIn.js';
export { default as assignInWith } from './assignInWith.js';
9. splitChunk 打包文件 index.js的分割
目前, 所有的js文件, 包括自己的和node_module的,全都打包在了一個(gè)文件index.js中.
包括: jquery, lodash, jquery-flexslider, 一共1.6M.這就很大. 所以現(xiàn)在我們要分割這個(gè)文件
注意: 通俗的講,"chunks" 是指交給webpack處理的文件,例如:js/css/img文件,node_module里導(dǎo)入的插件. 通過(guò)import的方式引入的模塊或文件都可以稱(chēng)之為"chunks"。
-
把自己項(xiàng)目的業(yè)務(wù)js文件和node_module的插件文件分離. 因?yàn)閚ode_module里是插件, 一個(gè)模塊不會(huì)依賴其他模塊. 相對(duì)好分割. 但是自己的業(yè)務(wù)文件. 由于有依賴關(guān)系不好分割.
所以 先把業(yè)務(wù)文件和插件文件分割. -
分割是有最小粒度的, 每一個(gè)被
import導(dǎo)入的資源,庫(kù),組件都是一個(gè)chunk. 只能是不同chunk之間進(jìn)行組合.一個(gè)chunk不能分割成兩個(gè)文件. -
optimization.splitChunks配置分割方式. 這里的配置項(xiàng)更像是分析配置. 簡(jiǎn)單來(lái)說(shuō)就是先打包成一個(gè)文件index.js. 然后, 如果某些chunk單獨(dú)打包出來(lái)符合配置的條件.就會(huì)把他單獨(dú)打包出來(lái).否則就合并到同一的index.js里-
chunks: 要分析的類(lèi)型.
initial就是從webpack.config.js的entry屬性里多入口分離的文件.也就是業(yè)務(wù)組件. 比如
{ entry: { index: "./src/index.js", login: "./src/login.js", }, }splitChunks配置的屬性就會(huì)對(duì)業(yè)務(wù)模塊的代碼進(jìn)行分割async應(yīng)該是從node_module里導(dǎo)入的模塊的分割(不確定).all將業(yè)務(wù)代碼和node_module里的代碼進(jìn)行分割. 就是index.js里只有業(yè)務(wù)代碼.node_module里的工具代碼單獨(dú)打包一個(gè)文件(或多個(gè)文件).- chunks的類(lèi)型的效果受minSize影響. 達(dá)到minsize大小了,才會(huì)單獨(dú)作為一個(gè)包. 沒(méi)有達(dá)到則還是都在index.js里.
-
minSize: 10 * 1024, 單位bite, 10 * 1024就是10kb. 這里的
minSize是如果某個(gè)chunk打包后有10kb則會(huì)被單獨(dú)打包, 否則就放到index.js里,哪怕index.js已經(jīng)很大了.也是如此. 也就是說(shuō)大文件單獨(dú)作為一個(gè)chunk, 小文件都打包到index.js里. -
name: 打包后的文件名,可以是函數(shù). 如果是多入口項(xiàng)目(比如login, index). 目前name的函數(shù)里沒(méi)有entry, 無(wú)法區(qū)分具體是哪個(gè)入口. 所以可以直接用默認(rèn)的名字.
- 默認(rèn)名稱(chēng)是由打包的文件名拼接而成的.比如里面有juqry和lodash, 那名字里就是
vendors-node_modules_jquery_-node_modules_lodash_lodash_js.540af9.js - 如果login和index拆出來(lái)的splitChunks文件的構(gòu)成一樣.比如都是juqry和lodash, 那么名字就是會(huì)一樣. 但是沒(méi)關(guān)系,因?yàn)槔锩鎯?nèi)容也一樣.
- 默認(rèn)名稱(chēng)是由打包的文件名拼接而成的.比如里面有juqry和lodash, 那名字里就是
-
cacheGroups: 分組打包, 單獨(dú)打包一個(gè)jquery, test模塊名匹配,name打包后的名稱(chēng).chunks類(lèi)型.
jquery: { test: /jquery\.js/, name: 'jquery', chunks: 'all', }, -
一般來(lái)說(shuō)minSize可以設(shè)為300kb, 注意這里的300kb是在生產(chǎn)環(huán)境下壓縮后的文件大小,不是開(kāi)發(fā)環(huán)境的文件大小.
-
{
optimization: {
splitChunks: {
chunks: 'all',
minSize: 1 * 1024,
name: 'common',
cacheGroups: {
jquery: {
test: /jquery\.js/,
name: 'jquery',
chunks: 'all',
},
'lodash-es': {
name: 'lodash-es',
test: /lodash-es/,
chunks: 'all',
}
}
},
},
}
10. ejs 原始項(xiàng)目的公共模板
- 下載ejs, ejs-loader
npm i ejs
npm i ejs-loader -D
- 配置ejs-loader
module: {
rules: [
{
test: /\.ejs$/i,
loader: 'ejs-loader',
options: {
esModule: false,
}
}
]
},
- 創(chuàng)建ejs文件
創(chuàng)建src/ejs/header.ejs文件
<p class="fl">
<a href="login.html" id="login">登錄</a>
<a href="#" id="reg">注冊(cè)</a>
</p>
- 使用ejs文件
<body>
<!-- 函數(shù)參數(shù)里可以傳遞數(shù)據(jù) -->
<%= require('./ejs/header.ejs')() %>
</body>
11. clean 每次打包后都清空dist
在webpack5, clean-webpack-plugin已經(jīng)被集成到了webpack里,成了默認(rèn)插件了. 可以直接用webpack.config.js里的配置控制
module.exports = {
//...
output: {
clean: true, // 在生成文件之前清空 output 目錄
},
};
12. copy-webpack-plugin, 將源文件中的某些文件直接復(fù)制到dist包中.
適用范圍:
- 比如說(shuō)有些靜態(tài)文件. 并不被html文件引用. 而是可以直接在瀏覽器查看, 單獨(dú)占一個(gè)地址. 比如一些pdf文件(同意協(xié)議, 法律條文),
- 這些文件由于不被html引用, 所以不會(huì)被webpack處理, 也就不會(huì)直接出現(xiàn)在dist目錄中.
- 又不能每次都手動(dòng)復(fù)制過(guò)去, 所以有了
copy-webpack-plugin, 幫我們把這些文件直接復(fù)制到dist里面. - 配置:
const CopyPlugin = require("copy-webpack-plugin");
{
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(rootPath, "./src/static"),
to: path.resolve(rootPath, './dist/txt'),
}
]
})
]
}
13. vue-loader, @vue/compiler-sfc , vue-template-compiler
- vue-loader: 識(shí)別
.vue文件, 可以將.vue文件里的html, css, js識(shí)別出來(lái). vue-loader@15版本以上的可以識(shí)別vue3代碼 - @vue/compiler-sfc: 將vue-loader識(shí)別出來(lái)的html, css,js進(jìn)行進(jìn)一步處理, 生成vue組件.
- vue-template-compiler: 專(zhuān)門(mén)針對(duì)
<template>標(biāo)簽進(jìn)行處理. @vue/compiler-sfc可以對(duì)template,script, style所有標(biāo)簽都處理,但是沒(méi)有vue-template-compiler專(zhuān)精. - 在webpack配置中, 只用配置vue-loader, 另外兩個(gè) @vue/compiler-sfc , vue-template-compiler是vue-loader調(diào)用的, 只要存在就可以了.
vue-loader的使用
// 跟vue-loader配套使用的插件
const { VueLoaderPlugin } = require('vue-loader')
// webpack的配置
{
module: {
rules: [
{
// 此處沒(méi)有ts的適配.只是識(shí)別vue文件. ts以后再說(shuō)
test: /\.vue$/,
loader: 'vue-loader',
}
]
},
plugins: [
// vue-loader的配套插件
new VueLoaderPlugin(),
]
}
14. devtools配置sourceMap
在瀏覽器看源代碼
devtools: string
- eval: 只展示打包后的代碼, 不展示源碼
- "eval-source-map": 展示源代碼. 此處沒(méi)有管ts. ts的解析另說(shuō).
- 要在瀏覽器上看到自己的業(yè)務(wù)源代碼, 最好是通過(guò)控制臺(tái)console里的log,點(diǎn)擊對(duì)應(yīng)文件查看. 直接看source分不清哪個(gè)是哪個(gè).
15. vue-router
- npm install vue-router@3 // npm install vue-router 默認(rèn)的是vue-router@4, 4對(duì)應(yīng)的是vue3, 不能用于vue2
- router.js
import Home from './page/home.vue';
import VueRouter from 'vue-router';
import Vue from 'vue'
/*vue.use的用處
1. 創(chuàng)建router-link, router-view標(biāo)簽.
2. 注冊(cè) this.$router, this.$route 對(duì)象.
*/
Vue.use(VueRouter);
// 路由配置
const routes = [
{
path: "/",
redirect: 'home',
},
{
path: "/home",
name: 'home',
component: Home,
}
]
// 創(chuàng)建router實(shí)例.配置其他參數(shù).
const Router = new VueRouter({
routes,
})
export default Router;
- 在main.js里注冊(cè)router
import Vue from 'vue';
import App from "./App.vue";
import router from './router.js';
new Vue({
router,
render: h=> h(App)
}).$mount("#app");
- 在App.vue里使用router-view
<template>
<router-view></router-view>
</template>
16. mpa改造
當(dāng)前的單頁(yè)面應(yīng)用只有index.html一個(gè)入口. 不利于搜索引擎識(shí)別頁(yè)面內(nèi)容. 對(duì)于頁(yè)面在搜索引擎的排名不利. 為了對(duì)項(xiàng)目進(jìn)行seo優(yōu)化.
我們把項(xiàng)目改成多頁(yè)面應(yīng)用, 每一個(gè)頁(yè)面都在dist里有一個(gè)對(duì)應(yīng)的入口html文件.比如login.html, home.html
核心原則就是: 把每一個(gè)頁(yè)面都當(dāng)成一個(gè)項(xiàng)目去處理
- 每一個(gè)頁(yè)面都有一個(gè)入口文件, 比如"src/mpa/home.js", "src/mpa/login.js"
import Vue from 'vue';
import home from "../page/home.vue";
new Vue({
// 這里的home本來(lái)是app.vue但是現(xiàn)在由于只展示home組件,所以可以直接放home, 不再需要router.
render: h=> h(home)
}).$mount("#app");
- 新建
webpack.vue.mpa.config.js. 進(jìn)行mpa的項(xiàng)目配置- entry改成多個(gè)
entry: {
// 'index': path.resolve(rootPath, "./src/main.js"),
'home': path.resolve(rootPath, "./src/mpa/home.js"),
'login': path.resolve(rootPath, "./src/mpa/login.js"),
},
2. HtmlWebpackPlugin配置多個(gè), 在dist里生成多個(gè)html文件
// 用index.html模板在dist下生成一個(gè)html文件
new HtmlWebpackPlugin({
filename: 'login.html', // 最后生成的login的入口文件
template: path.resolve(rootPath, "./public/index.html"), // 模板用統(tǒng)一的模板
// 當(dāng)前打包入口 加載的js模塊, 這里的模塊名是 entry里面的key對(duì)應(yīng)的模塊
chunks: ['login'],
}),
- 修改package.json里的script,添加mpa命令
"scripts": {
"start:mpa": "webpack-dev-server --config ./build/webpack.vue.mpa.config.js",
"build:mpa": "webpack --config ./build/webpack.vue.mpa.config.js"
},
vue3改造
vue3比vue2更快, 更好用. 打包后體積更小, 反應(yīng)更快. 并且vue2已經(jīng)不在被支持,所以我們的vue2項(xiàng)目要升級(jí)到vue3.
- vue3: 3.4.38, vue-router: 4.4.3, vue-loader: 16.8.3, 在package.json里配置
"vue": "^3.0.0",就會(huì)自己去找3版本的最新版本. - vue-router的創(chuàng)建
import Home from './page/home.vue';
//createRouter創(chuàng)建router對(duì)象, createMemoryHistory創(chuàng)建router的歷史記錄模式
import {createRouter, createMemoryHistory} from 'vue-router';
const routes = [
{
path: "/home",
name: 'home',
component: Home,
},
];
const router = createRouter({
history: createMemoryHistory(),
routes,
})
export default router;
- vue的創(chuàng)建. main.js
import router from './router.js';
import App from "./App.vue";
import {createApp} from 'vue'
const app = createApp(App).use(router).mount("#app");
- vue3的語(yǔ)法和router的使用
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
export default {
setup() {
const router = useRouter();
const goLogin = () => {
router.push('/login');
};
const message = ref('li');
onMounted(() => {
message.value = '李飛';
});
return {
message,
goLogin,
};
},
};
英語(yǔ)
- generator: 發(fā)電機(jī), 發(fā)生器. 引申為創(chuàng)建含義, 創(chuàng)建文件的配置
- provider: 提供者, 供應(yīng)者, 在webpack里是, 遇到未定義的變量 提供引入模塊.
- optimize: 使...優(yōu)化. optimization優(yōu)化項(xiàng). 使用webpack對(duì)打包的優(yōu)化配置項(xiàng).
- exclude: 排除, 不是用優(yōu)化程序的文件目錄.
- treeshaking: tree,樹(shù), shaking搖動(dòng), treeshaking搖動(dòng)樹(shù)木, 把不用的葉子搖晃下來(lái). 意為打包時(shí)不打包沒(méi)有使用過(guò)的函數(shù)代碼
每個(gè)技術(shù)要搞懂的內(nèi)容.
- 出現(xiàn)這個(gè)技術(shù)之前的現(xiàn)狀是什么.
- 這個(gè)現(xiàn)狀有什么問(wèn)題, 這個(gè)技術(shù)是為了解決什么問(wèn)題而出現(xiàn)的.
- 解決方案是什么.
- 解決后比原來(lái)好在哪里(選)
遇到的問(wèn)題
-
devServer配置不生效問(wèn)題.
問(wèn)題:- 在webpack.config.js里配置了
webpack-dev-server. port設(shè)為9000. - 在package.json的script里配置了命令
start: webpack-dev-server. - 執(zhí)行npm start后. port是8080.
原因:
- 在
webpack-dev-server命令中, 默認(rèn)的webpack.config.js的位置實(shí)在根目錄, 而我的是在'build'文件夾下. devserver沒(méi)有找到配置文件,所以用的默認(rèn)配置.所以port是8080. "build"命令配置了配置文件位置, 所以沒(méi)有出問(wèn)題
解決方案:
- 修改start命令為:
"start": "webpack-dev-server --config ./build/webpack.config.js",
- 在webpack.config.js里配置了
性能優(yōu)化
1. 多入口打包, js入口的分離.
每個(gè)入口只打包他們自己的文件, 而不是全部js文件. 詳見(jiàn) `9. splitChunk 打包文件 index.js的分割`;
2. 入口文件優(yōu)化.
index.js文件過(guò)大. 把index.js分割成多個(gè)大小適當(dāng)?shù)奈募? 比如用`mini-css-extract-plugin`單獨(dú)把css文件抽離出來(lái)(style-loader是把css內(nèi)容直接打包到index.js里的.)
3. 代碼壓縮
js壓縮: terser-webpack-plugin , css代碼壓縮: css-minimizer-webpack-plugin;
4. treeshaking
未被調(diào)用的函數(shù)不打包進(jìn)dist里. 比如用lodash里的工具函數(shù), 用哪個(gè)就打包哪個(gè),而不是整個(gè)打包進(jìn)去. 常用的就那幾個(gè).
使用別的工具函數(shù)的時(shí)候,一定要用解構(gòu)賦值來(lái)獲取, 防止引入不必要的函數(shù).
5. splitChunks
針對(duì)所有js文件打包成的index.js進(jìn)行分割. 比如首屏優(yōu)化. 在單頁(yè)面應(yīng)用中, 進(jìn)入頁(yè)面時(shí)是會(huì)把所有的公共js文件都加載的. 但是首頁(yè)可能只用到很少的公共js庫(kù).
這時(shí)可以把 "首頁(yè)的業(yè)務(wù)文件", "首頁(yè)用到的公共js文件"單獨(dú)拉出來(lái). 首頁(yè)用不到的公共文件單獨(dú)放一個(gè)文件.這樣當(dāng)進(jìn)入頁(yè)面時(shí),首頁(yè)的業(yè)務(wù)文件, 首頁(yè)用的公共js文件加載完后頁(yè)面就展示了. 首頁(yè)用不到的公共文件還未返回時(shí),不影響頁(yè)面展示. 可以在后面慢慢請(qǐng)求.
export function get(){}
import { get } from 'tools';
浙公網(wǎng)安備 33010602011771號(hào)