本文目錄:
- 1.webpack的定義及基礎(chǔ)核心概念
- 2.webpack構(gòu)建原理
- 3.webpack運(yùn)行的基本流程
- 4.webpack 動(dòng)態(tài)加載的實(shí)現(xiàn)原理及使用方法
- 5.loader的原理及手寫loader的思路
- 6.plugin的原理及手寫plugin的思路
- 7.loader和plugin的區(qū)別
- 8.tree sharking是什么
- 9.什么是webpack熱更新
- 10.介紹下webpack5的新特性
- 11.Webpack性能優(yōu)化
- 12.在前端工程化涌現(xiàn)出眾多工具, 試說(shuō)明webpack與grunt、gulp的不同?
- 13.npm打包時(shí)需要注意哪些?如何利用webpack來(lái)更好的構(gòu)建?
1.webpack的定義及基礎(chǔ)核心概念
webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時(shí),它會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖(dependency graph),其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle。
webpack有四個(gè)核心概念:
入口(entry),輸出(output),loader,插件(plugins)
webpack的入口文件模板結(jié)構(gòu):
module.exports = {
//入口配置
entry: '',
//出口配置
output: '',
//模塊配置
module: {
rules: [
{
test: /\.css/,
use: ["style-loader", "css-loader"]
}
]
},
//插件配置
plugins: {},
//模式配置,開發(fā)模式還是生產(chǎn)模式
mode:'',
//開發(fā)服務(wù)器配置
devServer: {},
//解析配置
resolve: {}
}
2.webpack構(gòu)建原理
webpack.config.js導(dǎo)出一個(gè)Object對(duì)象(或者導(dǎo)出一個(gè)Function,或者導(dǎo)出一個(gè)Promise函數(shù),還可以導(dǎo)出一個(gè)數(shù)組包含多份配置)。Webpack從入口文件開始,識(shí)別出源碼中的模塊化導(dǎo)入語(yǔ)句,遞歸地找出所有依賴,然后把入口文件和所有依賴打包到一個(gè)單獨(dú)的文件中(即一個(gè)chunk),這就是所謂的模塊打包。
3.webpack運(yùn)行的基本流程
webpack運(yùn)行的基本流程分為初始化、編譯、輸出三個(gè)階段.
初始化:
從配置文件和shell文件讀取、合并參數(shù);
加載plugin
實(shí)例化compiler
編譯:
從entry發(fā)出,針對(duì)每個(gè)module串行調(diào)用對(duì)應(yīng)loader編譯文件內(nèi)容
找到module依賴的module,遞歸進(jìn)行編譯處理
輸出:
把編譯后module組合成chunk
把chunk轉(zhuǎn)換成文件,輸出到文件系統(tǒng)
Webpack 的運(yùn)行流程是一個(gè)串行的過(guò)程,從啟動(dòng)到結(jié)束會(huì)依次執(zhí)行以下流程:
初始化參數(shù):從配置文件和 Shell 語(yǔ)句中讀取與合并參數(shù),得出最終的參數(shù);
開始編譯:用上一步得到的參數(shù)初始化 Compiler 對(duì)象,加載所有配置的插件,執(zhí)行對(duì)象的 run 方法開始執(zhí)行編譯;
確定入口:根據(jù)配置中的 entry 找出所有的入口文件;
編譯模塊:從入口文件出發(fā),調(diào)用所有配置的 Loader 對(duì)模塊進(jìn)行翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過(guò)了本步驟的處理;
完成模塊編譯:在經(jīng)過(guò)第4步使用 Loader 翻譯完所有模塊后,得到了每個(gè)模塊被翻譯后的最終內(nèi)容以及它們之間的依賴關(guān)系;
輸出資源:根據(jù)入口和模塊之間的依賴關(guān)系,組裝成一個(gè)個(gè)包含多個(gè)模塊的 Chunk,再把每個(gè) Chunk 轉(zhuǎn)換成一個(gè)單獨(dú)的文件加入到輸出列表,這步是可以修改輸出內(nèi)容的最后機(jī)會(huì);
輸出完成:在確定好輸出內(nèi)容后,根據(jù)配置確定輸出的路徑和文件名,把文件內(nèi)容寫入到文件系統(tǒng)。
在以上過(guò)程中,Webpack 會(huì)在特定的時(shí)間點(diǎn)廣播出特定的事件,插件在監(jiān)聽到感興趣的事件后會(huì)執(zhí)行特定的邏輯,并且插件可以調(diào)用 Webpack 提供的 API 改變 Webpack 的運(yùn)行結(jié)果
4.webpack 動(dòng)態(tài)加載的實(shí)現(xiàn)原理及使用方法
在代碼中所有被import()的模塊,都將打成一個(gè)單獨(dú)的包,放在chunk存儲(chǔ)的目錄下。在瀏覽器運(yùn)行到這一行代碼時(shí),就會(huì)自動(dòng)請(qǐng)求這個(gè)資源,實(shí)現(xiàn)異步加載。
ES6的import語(yǔ)法告訴我們,模塊只能做靜態(tài)加載。
所謂靜態(tài)加載,就是你不能寫成如下形式:
let filename = 'module.js';
import {mod} from './' + filename.
//也不能寫成如下形式:
if(condition) {
import {mod} from './path1'
} else {
import {mod} from './path2'
}
先webpack4以后的版本的支持下,import可以進(jìn)行動(dòng)態(tài)加載,大致用法如下:import()接收一個(gè)路徑參數(shù),然后通過(guò)then的方式引入模塊
let filename = 'module.js';
import('./' + filename). then(module =>{
console(module);
}).catch(err => {
console(err.message);
});
//如果你知道 export的函數(shù)名
import('./' + filename). then(({fnName}) =>{
console(fnName);
}).catch(err => {
console(err.message);
});
這里有一點(diǎn)要注意的是:
import的加載是加載的模塊的引用。而import()加載的是模塊的拷貝,就是類似于require(),怎么來(lái)說(shuō)明?看下面的例子:
module.js 文件:
export let counter = 3;
export function incCounter() {
counter++;
}
main.js 文件:
let filename = 'module.js';
import('./' + filename).then(({counter, incCounter})=>{
console.log(counter); //3
incCounter();
console.log(counter); //3
});
原本的import寫法:
import {counter, incCounter} from './module.js';
console.log(counter); //3
incCounter();
console.log(counter); //4
5.loader的原理及手寫loader的思路
loader是 webpack 用于在編譯過(guò)程中解析各類文件格式,并輸出;
loader(加載器)是一個(gè)代碼轉(zhuǎn)換器,它由 webpack 的 loader runner 執(zhí)行調(diào)用,接收原始資源數(shù)據(jù)作為參數(shù)(當(dāng)多個(gè)加載器聯(lián)合使用時(shí),上一個(gè)loader的結(jié)果會(huì)傳入下一個(gè)loader),最終輸出 javascript 代碼(和可選的 source map)給 webpack 做進(jìn)一步編譯。
手寫loader的思路:
loader本質(zhì)上就是一個(gè) node 模塊,通過(guò)寫一個(gè)函數(shù)來(lái)完成自動(dòng)化的過(guò)程。
這里通過(guò)寫一個(gè)最簡(jiǎn)單的loader來(lái)理解手寫loader的思路。
當(dāng)只有一個(gè) loader 應(yīng)用于資源文件時(shí),它接收源碼作為參數(shù),輸出轉(zhuǎn)換后的 js 代碼。文件路徑:loaders/simple-loader.js
module.exports = function loader (source) {
console.log('simple-loader is working');
return source;
}
這就是一個(gè)最簡(jiǎn)單的 loader 了,這個(gè) loader 啥也沒(méi)干,就是接收源碼,然后原樣返回,為了證明這個(gè)loader被調(diào)用了,我在里面打印了一句話‘simple-loader is working’。
測(cè)試這個(gè) loader:
若是使用 npm 安裝的第三方 loader,直接寫 loader 的名字就可以了。但是現(xiàn)在用的是自己開發(fā)的本地 loader,需要我們手動(dòng)配置路徑,告訴 webpack 這些 loader 在哪里。
// webpack.config.js
const path = require('path');
module.exports = {
entry: {...},
output: {...},
module: {
rules: [
{
test: /\.js$/,
// 直接指明 loader 的絕對(duì)路徑
use: path.resolve(__dirname, 'loaders/simple-loader')
}
]
}
}
執(zhí)行webpack編譯,可以看到,控制臺(tái)輸出 ‘simple-loader is working’。說(shuō)明 loader 成功被調(diào)用。
6.plugin的原理及手寫plugin的思路
wenpack根據(jù)自己的工作機(jī)制提供了許多hooks,類似于Vue的生命周期。
例如:run(開始編譯階段),make( 從 entry 開始遞歸分析依賴,準(zhǔn)備對(duì)每個(gè)模塊進(jìn)行 build),done(完成所有的編譯過(guò)程)
plugin必須是一個(gè)函數(shù),或者是一個(gè)包含apply的對(duì)象。一般來(lái)說(shuō)我們都會(huì)定義一個(gè)類型,然后在這個(gè)類型中定義apply方法,最后再通過(guò)這個(gè)類型來(lái)創(chuàng)建一個(gè)實(shí)例對(duì)象去使用這個(gè)插件。
例如下面這段代碼
const pluginName = 'myplugin'
module.exports = class myplugin {
apply(){}
}
這個(gè)apply方法接收一個(gè)叫compiler的參數(shù)對(duì)象,這個(gè)對(duì)象是webpack工作中最核心的對(duì)象,包含了此次打包構(gòu)建的所有配置信息,我們就可以通過(guò)這個(gè)對(duì)象去注冊(cè)鉤子函數(shù)。
const pluginName = 'myplugin'
module.exports = class myplugin {
apply(compiler){
compiler.hooks.run.tap(pluginName, () =>{
{
console.log('開始編譯');
}
})
}
}
我們想在run階段輸出‘開始編譯’這句話,在webpack.config.js中引入并配置
const myplugin = require('./myplugin')
...
plugins:[
new myplugin()
]
...
進(jìn)行webpack編譯,在控制臺(tái)可以看到在開始階段輸出了內(nèi)容,說(shuō)明plugin生效了。
7.loader和plugin的區(qū)別
對(duì)于loader,它是一個(gè)轉(zhuǎn)換器,將A文件進(jìn)行編譯形成B文件,這里操作的是文件,比如將A.scss轉(zhuǎn)換為A.css,單純的文件轉(zhuǎn)換過(guò)程。
plugin是一個(gè)擴(kuò)展器,它豐富了webpack本身,針對(duì)是loader結(jié)束后,webpack打包的整個(gè)過(guò)程,它并不直接操作文件,而是基于事件機(jī)制工作,會(huì)監(jiān)聽webpack打包過(guò)程中的某些節(jié)點(diǎn),執(zhí)行廣泛的任務(wù)。
不同的作用
- Loader直譯為"加載器"。Webpack將一切文件視為模塊,但是webpack原生是只能解析js文件,如果想將其他文件也打包的話,就會(huì)用到loader。 所以Loader的作用是讓webpack擁有了加載和解析非JavaScript文件的能力。
- Plugin直譯為"插件"。Plugin可以擴(kuò)展webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 運(yùn)行的生命周期中會(huì)廣播出許多事件,Plugin 可以監(jiān)聽這些事件,在合適的時(shí)機(jī)通過(guò) Webpack 提供的 API 改變輸出結(jié)果。
不同的用法
- Loader在module.rules中配置,也就是說(shuō)他作為模塊的解析規(guī)則而存在。 類型為數(shù)組,每一項(xiàng)都是一個(gè)Object,里面描述了對(duì)于什么類型的文件(test),使用什么加載(loader)和使用的參數(shù)(options)
- Plugin在plugins中單獨(dú)配置。 類型為數(shù)組,每一項(xiàng)是一個(gè)plugin的實(shí)例,參數(shù)都通過(guò)構(gòu)造函數(shù)傳入。
8.tree sharking是什么
Tree shaking 是一種通過(guò)清除多余代碼方式來(lái)優(yōu)化項(xiàng)目打包體積的技術(shù)。
我們?cè)陧?xiàng)目中創(chuàng)建一個(gè)utils.js文件:
export function add(a, b) {
console.log('add');
return a + b;
}
export function minus(a, b) {
console.log('minus');
return a - b;
}
export function multiply(a, b) {
console.log('multiply');
return a * b;
}
export function divide(a, b) {
console.log('divide');
return a / b;
}
index.js文件中導(dǎo)入utils.js的add方法并調(diào)用:
import { add } from './utils';
add(10, 2);
運(yùn)行npm run build后查看dist/bundle.js文件,可以發(fā)現(xiàn)utils.js中所有的代碼都打包了,并沒(méi)有像我們預(yù)期的那樣只打包add()函數(shù)。
CommonJS的動(dòng)態(tài)特性模塊意味著tree shaking不適用。因?yàn)樗遣豢赡艽_定哪些模塊實(shí)際運(yùn)行之前是需要的或者是不需要的。在ES6中,進(jìn)入了完全靜態(tài)的導(dǎo)入語(yǔ)法:import。ES6的import語(yǔ)法完美可以使用tree shaking,因?yàn)榭梢栽诖a不運(yùn)行的情況下就能分析出不需要的代碼。
webpack4以后的版本,只需要將mode設(shè)置為production即可開啟tree shaking。
9.什么是webpack熱更新
模塊熱替換(HMR - Hot Module Replacement)允許在運(yùn)行時(shí)替換,添加,刪除各種模塊,而無(wú)需進(jìn)行完全刷新重新加載整個(gè)頁(yè)面。
一個(gè)帶有熱替換功能的webpack.config.js 文件的配置如下,做了這么幾件事
- 引入了webpack庫(kù)
- 使用了new webpack.HotModuleReplacementPlugin()
- 設(shè)置devServer選項(xiàng)中的hot字段為true
10.介紹下webpack5的新特性
1.通過(guò)
嵌套tree-shaking的實(shí)現(xiàn)
移除Node.js polyfills 自動(dòng)加載功能
有效減少打包后的文件體積。
2.生成的代碼不再僅僅是ES5,也會(huì)生成 ES6 的代碼
3.optimization配置中優(yōu)化了minSize&maxSize的配置方式,對(duì)js和css有了區(qū)分,單位是kb
optimization: {
runtimeChunks: {},
splitChunks: {},
// 在文件大小為0-30kb的情況下進(jìn)行文件分割
minSize: {
javaScript: 0,
style: 0
},
maxSize: {
javaScript: 30,
style: 30
}
}
4.在配置文件中使用cache: {type: "filesystem"}配置實(shí)現(xiàn)持久化緩存,提高構(gòu)建速度
11.Webpack性能優(yōu)化
優(yōu)化可以從兩個(gè)方面考慮,一個(gè)是優(yōu)化開發(fā)體驗(yàn),一個(gè)是優(yōu)化輸出質(zhì)量。
優(yōu)化開發(fā)體驗(yàn)
①縮小文件搜索范圍
resolve字段告訴webpack怎么去搜索文件,所以首先要重視r(shí)esolve字段的配置:
由于loader對(duì)文件轉(zhuǎn)換操作很耗時(shí),應(yīng)該盡量減少loader處理的文件,可以使用include命中需要處理的文件,縮小命中范圍。
②DllPlugin可以將特定的類庫(kù)提前打包然后引入
DllPlugin是webpack的內(nèi)置插件,這種方式可以極大的減少打包類庫(kù)的次數(shù),只有當(dāng)類庫(kù)更新版本才有需要重新打包,并且也實(shí)現(xiàn)了將公共代碼抽離成單獨(dú)文件的優(yōu)化方案
③HappyPack
因?yàn)镹ode是單線程運(yùn)行的,所以Webpack在打包的過(guò)程中也是單線程的,特別是在執(zhí)行Loader的時(shí)候,這樣會(huì)導(dǎo)致等待的情況,HappyPack可以將Loader的同步執(zhí)行轉(zhuǎn)換為并行的,HappyPack插件需要另外安裝。
④使用source-map優(yōu)化代碼調(diào)試
在webpack.config.js中加入devtool:'source-map'可以讓構(gòu)建后代碼出錯(cuò),會(huì)通過(guò)映射關(guān)系追蹤源代碼錯(cuò)誤。
實(shí)際開發(fā)中我們往往只需要在開發(fā)環(huán)境中開啟source-map
const isProd = process.env.NODE_ENV === 'production';
module.exports = {
devtool: isProd
? false
: '#cheap-module-source-map',
}
⑤熱更新HMR
利用webpack內(nèi)置插件HotModuleReplacementPlugin,無(wú)需在每次更改內(nèi)容時(shí)都重新加載整個(gè)頁(yè)面。
優(yōu)化輸出質(zhì)量
優(yōu)化輸出質(zhì)量最大的好處就是可以減少首屏的加載時(shí)間
①按需加載路由
如果我們把十幾個(gè)頁(yè)面甚至更多的路由頁(yè)面,把這些頁(yè)面全部打包進(jìn)一個(gè)JS文件的話,雖然將多個(gè)請(qǐng)求合并了,但是同樣也加載了很多并不需要的代碼,耗費(fèi)了更長(zhǎng)的時(shí)間。那么為了首頁(yè)能更快地呈現(xiàn)給客戶,這時(shí)候我們就可以使用按需加載,將每個(gè)路由頁(yè)面單獨(dú)打包為一個(gè)文件
②使用Tree Shaking,刪除項(xiàng)目中未被引用的代碼。
③開啟Scope Hoisting
Scope Hoisting直譯就是作用域提升,Scope Hoisting會(huì)分析出模塊之間的依賴關(guān)系,盡可能的把打包出來(lái)的模塊合并到一個(gè)函數(shù)中,讓W(xué)ebpack打包出來(lái)的代碼更小、運(yùn)行更快。
Scope Hoisting 是webpack內(nèi)置的功能,只要配置一個(gè)插件即可
module.exports = {
plugins: [
// 開啟 Scope Hoisting 功能
new webpack.optimize.ModuleConcatenationPlugin()
]
}
④區(qū)分環(huán)境--減小生產(chǎn)環(huán)境代碼體積
代碼運(yùn)行環(huán)境分為開發(fā)環(huán)境和生產(chǎn)環(huán)境,代碼需要根據(jù)不同環(huán)境做不同的操作,許多第三方庫(kù)中也有大量的根據(jù)開發(fā)環(huán)境判斷的if else代碼,構(gòu)建也需要根據(jù)不同環(huán)境輸出不同的代碼,所以需要一套機(jī)制可以在源碼中區(qū)分環(huán)境,區(qū)分環(huán)境之后可以使輸出的生產(chǎn)環(huán)境的代碼體積減小。Webpack中使用內(nèi)置DefinePlugin插件來(lái)定義配置文件適用的環(huán)境。
plugins:[
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
]
注意,JSON.stringify('production') 的原因是,環(huán)境變量值需要一個(gè)雙引號(hào)包裹的字符串,而stringify后的值是'"production"'
然后就可以在源碼中使用定義的環(huán)境:
if(process.env.NODE_ENV === 'production'){
console.log('你在生產(chǎn)環(huán)境')
doSth();
}else{
console.log('你在開發(fā)環(huán)境')
doSthElse();
}
⑤使用terser-webpack-plugin插件壓縮JS代碼
如果使用的是 webpack v5 或以上版本,你不需要安裝這個(gè)插件。webpack v5 自帶最新的 terser-webpack-plugin。如果使用 webpack v4,則必須安裝 terser-webpack-plugin v4 的版本。
npm install terser-webpack-plugin --save-dev
然后將插件添加到你的 webpack 配置文件中
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
⑥壓縮圖片資源
對(duì)于某些網(wǎng)站,圖像占據(jù)了頁(yè)面很大部分,雖然它們不會(huì)阻塞頁(yè)面渲染,但是它們?nèi)匀徽加昧撕艽笠徊糠謳?,在webpack中可以使用url-loader來(lái)優(yōu)化。
url-loader 可以將小型靜態(tài)文件內(nèi)聯(lián)到應(yīng)用程序中。如果不進(jìn)行配置,它將把接受一個(gè)傳遞的文件,將其放在已編譯的包旁邊,并返回該文件的url。但是,如果指定 limit 選項(xiàng),它將把小于這個(gè)限制的文件編碼為Base64 數(shù)據(jù)的 url 并返回這個(gè)url,這會(huì)將圖像內(nèi)聯(lián)到 JavaScript 代碼中,從而可以減少一個(gè)HTTP請(qǐng)求。
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif)$/,
loader: 'url-loader',
options: {
// Inline files smaller than 10 kB (10240 bytes)
limit: 10 * 1024,
},
},
],
}
};
12.在前端工程化涌現(xiàn)出眾多工具, 試說(shuō)明webpack與grunt、gulp的不同?
三者都是前端構(gòu)建工具,grunt和gulp在早期比較流行,現(xiàn)在webpack相對(duì)來(lái)說(shuō)比較主流,不過(guò)一些輕量化的任務(wù)還是會(huì)用gulp來(lái)處理,比如單獨(dú)打包CSS文件等。
grunt和gulp是基于任務(wù)和流(Task、Stream)的。類似jQuery,找到一個(gè)(或一類)文件,對(duì)其做一系列鏈?zhǔn)讲僮?,更新流上的?shù)據(jù), 整條鏈?zhǔn)讲僮鳂?gòu)成了一個(gè)任務(wù),多個(gè)任務(wù)就構(gòu)成了整個(gè)web的構(gòu)建流程。
webpack是基于入口的。webpack會(huì)自動(dòng)地遞歸解析入口所需要加載的所有資源文件,然后用不同的Loader來(lái)處理不同的文件,用Plugin來(lái)擴(kuò)展webpack功能。
所以總結(jié)一下:
從構(gòu)建思路來(lái)說(shuō)
gulp和grunt需要開發(fā)者將整個(gè)前端構(gòu)建過(guò)程拆分成多個(gè)Task,并合理控制所有Task的調(diào)用關(guān)系 webpack需要開發(fā)者找到入口,并需要清楚對(duì)于不同的資源應(yīng)該使用什么Loader做何種解析和加工復(fù)制代碼
對(duì)于知識(shí)背景來(lái)說(shuō)
gulp更像后端開發(fā)者的思路,需要對(duì)于整個(gè)流程了如指掌 webpack更傾向于前端開發(fā)者的思路
13.npm打包時(shí)需要注意哪些?如何利用webpack來(lái)更好的構(gòu)建?
Npm是目前最大的 JavaScript 模塊倉(cāng)庫(kù),里面有來(lái)自全世界開發(fā)者上傳的可復(fù)用模塊。你可能只是JS模塊的使用者,但是有些情況你也會(huì)去選擇上傳自己開發(fā)的模塊。 關(guān)于NPM模塊上傳的方法可以去官網(wǎng)上進(jìn)行學(xué)習(xí),這里只講解如何利用webpack來(lái)構(gòu)建。
NPM模塊需要注意以下問(wèn)題:
- 要支持CommonJS模塊化規(guī)范,所以要求打包后的最后結(jié)果也遵守該規(guī)則。
- Npm模塊使用者的環(huán)境是不確定的,很有可能并不支持ES6,所以打包的最后結(jié)果應(yīng)該是采用ES5編寫的。并且如果ES5是經(jīng)過(guò)轉(zhuǎn)換的,請(qǐng)最好連同SourceMap一同上傳。
- Npm包大小應(yīng)該是盡量小(有些倉(cāng)庫(kù)會(huì)限制包大?。?/li>
- 發(fā)布的模塊不能將依賴的模塊也一同打包,應(yīng)該讓用戶選擇性的去自行安裝。這樣可以避免模塊應(yīng)用者再次打包時(shí)出現(xiàn)底層模塊被重復(fù)打包的情況。
- UI組件類的模塊應(yīng)該將依賴的其它資源文件,例如
.css文件也需要包含在發(fā)布的模塊里。
基于以上需要注意的問(wèn)題,我們可以對(duì)于webpack配置做以下擴(kuò)展和優(yōu)化:
1.CommonJS模塊化規(guī)范的解決方案: 設(shè)置output.libraryTarget='commonjs2'使輸出的代碼符合CommonJS2 模塊化規(guī)范,以供給其它模塊導(dǎo)入使用
輸出ES5代碼的解決方案:使用babel-loader把 ES6 代碼轉(zhuǎn)換成 2.ES5 的代碼。再通過(guò)開啟devtool: 'source-map'輸出SourceMap以發(fā)布調(diào)試。
3.Npm包大小盡量小的解決方案:Babel 在把 ES6 代碼轉(zhuǎn)換成 ES5 代碼時(shí)會(huì)注入一些輔助函數(shù),最終導(dǎo)致每個(gè)輸出的文件中都包含這段輔助函數(shù)的代碼,造成了代碼的冗余。解決方法是修改.babelrc文件,為其加入transform-runtime插件
4.不能將依賴模塊打包到NPM模塊中的解決方案:使用externals配置項(xiàng)來(lái)告訴webpack哪些模塊不需要打包。
5.對(duì)于依賴的資源文件打包的解決方案:通過(guò)css-loader和extract-text-webpack-plugin來(lái)實(shí)現(xiàn),配置如下:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
// 增加對(duì) CSS 文件的支持
test: /\.css/,
// 提取出 Chunk 中的 CSS 代碼到單獨(dú)的文件中
use: ExtractTextPlugin.extract({
use: ['css-loader']
}),
},
]
},
plugins: [
new ExtractTextPlugin({
// 輸出的 CSS 文件名稱
filename: 'index.css',
}),
],
};