基礎(chǔ)
- 模塊化
CommonJS: 用于Node.js環(huán)境
// 導(dǎo)出
module.exports = moduleA.func;
// 導(dǎo)入
const moduleA = require( url );
AMD: 用于Node.js環(huán)境,瀏覽器雹食。異步方式家在模塊 -> requirejs
// 定義模塊
define( 'module', ['dep'], function(dep) {
return exports;
} )
// 導(dǎo)入模塊
require( ['module'], function(module) {} )
ES6模塊化: 需要轉(zhuǎn)化成es5運(yùn)行
// 導(dǎo)出
export function hello(){};
export default {};
// 導(dǎo)入
import { A } from url;
import B from url;
一直計(jì)劃說(shuō)詳細(xì)學(xué)一下webpack皂岔,然后由于各種因素拖到了現(xiàn)在条辟。 結(jié)合《深入淺出Webpack》和官方文檔俱萍。
概念: 靜態(tài)模塊打包器(module bundler)整袁, 將從入口開(kāi)始 構(gòu)建整個(gè)應(yīng)用的依賴(lài)關(guān)系圖挽拂,然后將所有模塊打包成一個(gè)或者多個(gè)bundle。
- 入口(entry): 應(yīng)用從哪個(gè)文件作為依賴(lài)圖的開(kāi)始人灼。
- 出口(output): 在哪里輸出根據(jù)依賴(lài)圖所創(chuàng)建的bundles围段, 以及如何命名這些文件⊥斗牛【默認(rèn)為./dist】
- 插件(plugins): loader 被用于轉(zhuǎn)換某些類(lèi)型的模塊奈泪,而插件則可以用于執(zhí)行范圍更廣的任務(wù)。插件的范圍包括灸芳,從打包優(yōu)化和壓縮段磨,一直到重新定義環(huán)境中的變量。
- 模式(mode): 可以啟用響應(yīng)模式下的webpack內(nèi)置的優(yōu)化(development耗绿, production)
- Chunk: 一個(gè)chunk由多個(gè)模塊組成苹支, 用于代碼合并與分割。
- module: 處理模塊的規(guī)則
- resolve:尋找模塊的規(guī)則
1. Entry: 可配置 多頁(yè)面應(yīng)用 或者 多入口的單頁(yè)應(yīng)用
const config = {
entry: './path/to/my/entry/file.js' // string 類(lèi)型
};
const config = {
entry: ['./path/to/my/entry/file1.js', './path/to/my/entry/file2.js'] // array 類(lèi)型
// 數(shù)組里的最后一個(gè)入口文件的模塊會(huì)被導(dǎo)出误阻。
};
const config = {
entry: { // object 類(lèi)型
pc: './pc/pc.js',
h5: './h5/h5.js',
}
};
2. Output:
const config = {
output: {
filename: "", // string 類(lèi)型
chunkFilename: ""债蜜, // string 需要在runtime根據(jù)chunk發(fā)送的請(qǐng)求去生成
path: path.resolve(__dirname, 'dist/assets'),
publicPath: ""究反, // 靜態(tài)資源的路徑寻定。 需要按照開(kāi)發(fā)環(huán)境或者生產(chǎn)環(huán)境配置
library:"", // string 導(dǎo)出庫(kù)的名稱(chēng)
libraryTarget: "", // enum 已何種方式導(dǎo)出庫(kù)
libraryExport: "", // string, array 導(dǎo)出那些子模塊
}
};
內(nèi)置變量列表:
- id: Chunk的唯一標(biāo)識(shí)精耐, 從0開(kāi)始
- name: Chunk的名稱(chēng)
- hash:Chunk的唯一標(biāo)識(shí)的Hash值
- chunkhash: Chunk內(nèi)容的Hash值
- query 模塊文件名 狼速? 后面的字符串
注: Hash的長(zhǎng)度是可以指定的如:[hash:8] ,默認(rèn)20
其他配置項(xiàng) 在官方文檔中有介紹或者后續(xù)的筆記中更新卦停。
3. Module: 如何處理不同類(lèi)型的模塊
const config = {
module: {
noParse: /jquery/ , // 忽略部分文件的解析和處理( 被忽略的文件不該包含import, require, define)
rules: [ // 配置Loader
{
test: /\.css/, // 正則表達(dá)式的匹配規(guī)則向胡, 也可是個(gè)array
use: [], // 數(shù)組中可以是string, object
enforce: "pre", // enum ["pre", "post"]
include: path.resolve(__dirname, 'src')惊完,// 僅匹配src目錄中的文件
exclude: path.resolve(__dirname, 'dist')僵芹,// 排除dist目錄中的文件
and: [], // 必須匹配所有條件
or: [],
not: [],
}
],
parser: { // 指定解析器的開(kāi)關(guān), 精確控制哪些語(yǔ)法可以被解析
amd: false,
commonjs: true,
}
}
};
其中當(dāng)use中,設(shè)置為對(duì)象時(shí)小槐, 可以向其loader傳入多個(gè)參數(shù)
use: [
{
loader: "", // 所使用的loader
options: {}, // 向loader傳入的參數(shù)
}
]
使用oneOf拇派,對(duì)匹配規(guī)則進(jìn)行嵌套,
rules: [ // 配置Loader
{
test: /\.css/,
oneOf: [ // 可以指定嵌套規(guī)則
{
resourceQuery: /inline/, // foo.css?inline
use: 'url-loader'
},
{
resourceQuery: /external/, // foo.css?external
use: 'file-loader'
}
],
}
]
配置loader 通過(guò)一下方式完成:
- 條件匹配: 通過(guò)test,include件豌,exclude
- 應(yīng)用規(guī)則: 通過(guò)use應(yīng)用loader
- 重置順序: 默認(rèn)loader的順序是從右向左的疮方, 使用enforce選項(xiàng)將loader的執(zhí)行順序改變
4. Resolve: 模塊如何被解析, (webpack本身含有默認(rèn)值)
const config = {
resolve: {
alias: { // 創(chuàng)建別名茧彤。 使引用是更方便骡显,避免過(guò)多的相對(duì)路徑
images: path.resolve(__dirname, 'src/images/')
css$: path.resolve(__dirname, 'src/assets/css') // $ 標(biāo)識(shí)精準(zhǔn)匹配
},
extensions: [".js",".json"], // 當(dāng)無(wú)后綴名時(shí),默認(rèn)自動(dòng)帶上后綴解析
mainFiles: [], // 指定導(dǎo)入模塊時(shí) 導(dǎo)入的哪部分代碼
modules: ["node_modules"], // 默認(rèn)只去node_modules中尋找第三方模塊
enforceExtension: false, // 允許無(wú)擴(kuò)展名文件的引用
unsafeCache: /\aa/, // 開(kāi)啟僅緩存aa模塊 regex, array, boolean
plugins: [], // 額外的解析插件列表
}
}
mainFiles棘街, 默認(rèn)為["browser", "module", "main"], 默認(rèn)順序
在其他target時(shí)蟆盐, 默認(rèn)為["module","main"]
即 對(duì)應(yīng) 所引用包的package.json中的
{
main: "build/d3.Node.js",
browser: "build/d3.js",
module: "index",
}
5. Plugins:
const config = {
plugins: [ // array
// 每項(xiàng)是一個(gè)插件的實(shí)例承边, 將參數(shù)通過(guò)構(gòu)造函數(shù)傳入
new CommonsChunkPlugin({ // 將所有公共代碼提取到common代碼塊中
name: "common",
chunks: ["a","b"]
})
]
}
6. DevServer: 在開(kāi)發(fā)中的行為
const config = {
devServer: {
host: "", // 默認(rèn)為localhost遭殉, 設(shè)置為ip 供外部訪(fǎng)問(wèn)
port: "", // 監(jiān)聽(tīng)的端口, 默認(rèn)8080
inline: true, // false 時(shí) 責(zé)啟用iframe模式博助, true為嵌入bundle中
allowedHosts: [], // 設(shè)置白名單
compress: true, // 啟用gzip壓縮
contentBase: path.join(__dirname, "public"), // 從哪提取靜態(tài)文件, 默認(rèn)當(dāng)前執(zhí)行的目錄 ./
disableHostCheck: false, // 關(guān)閉host檢查险污,使其他設(shè)備也能訪(fǎng)問(wèn)本地服務(wù)
lazy: true, // 開(kāi)啟惰性模式,僅在請(qǐng)求時(shí)編譯富岳,即不監(jiān)聽(tīng)文件改動(dòng)
filename: "", // 只在請(qǐng)求該文件時(shí)編譯蛔糯, 必須開(kāi)啟惰性模式
headers: {}, // 在所有想用中添加首部?jī)?nèi)容
hot: true, // 開(kāi)啟模塊熱替換,僅刷新改變的模塊
clientLogLevel: "info", // enum 客戶(hù)端的日志級(jí)別窖式,默認(rèn)info
https: true, // 默認(rèn)使用http服務(wù)蚁飒,開(kāi)啟https 后自動(dòng)生成一份證書(shū),也可用{}配置自己的證書(shū),讀文件
open: true, // 第一次構(gòu)建后 自動(dòng)打開(kāi)瀏覽器
proxy: {
"/api": "http://localhost:3000",
"/users": {
target: "https://localhost:3000",
pathRewrite: {"^/users" : ""}, // 將路徑重寫(xiě) 如 /users/login -> /login
secure: false, // 若代理到https服務(wù)萝喘,則需要將secure設(shè)為false
bypass: function(req, res, proxyOptions) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
}
}
}
},
quiet: true, // 除初始啟動(dòng)信息外都不會(huì)打印到控制臺(tái)
}
}
proxy: [{ // 針對(duì)多個(gè)請(qǐng)求 進(jìn)行代理
context: ["/auth", "/api"],
target: "http://localhost:3000",
}]
7. Devtool:配置source map
const config = {
devtool: "none" // 構(gòu)建source-map方便調(diào)試 enum
}
具體的選項(xiàng)和構(gòu)建速度 在官方文檔中有詳細(xì)的表格
8. Target:配置source map
const config = {
target: "web", // enum 默認(rèn)web淮逻, 還有node,webworker阁簸, electron等
const webpack = require("webpack");
const options = {
target: (compiler) => { // function 使用非自帶的target的插件
compiler.apply(
new webpack.JsonpTemplatePlugin(options.output),
new webpack.LoaderTargetPlugin("web")
);
}
};
9. Watch: 監(jiān)聽(tīng)規(guī)則
const config = {
watch: true, // 默認(rèn)false爬早, 在devServer中默認(rèn)開(kāi)啟
watchOptions: {
ignored: /node_modules/, // 或者使用"files/**/*.js" 這種形式
poll: 1000, // number, boolean 每秒進(jìn)行輪詢(xún)
aggregateTimeout: 300, // 監(jiān)聽(tīng)到變化后 延遲300ms再執(zhí)行
}
}
10. Externals不打包某些模塊
const config = {
externals: {
jquery: 'jQuery' // string, array. object, function, regex
}
}
因?yàn)槿忠肓艘恍┠K或變量,然后import的時(shí)候启妹,會(huì)使webpack將模塊再打包一次筛严,所以會(huì)出現(xiàn)重復(fù)的內(nèi)容,使用externals排除在外饶米。
11. Performance
const config = {
performance: {
hints: "warning"桨啃, // 打開(kāi)提示,在開(kāi)發(fā)環(huán)境使用warning檬输,生產(chǎn)error
maxEntrypointSize: 400000, // 根據(jù)入口起點(diǎn)的最大體積优幸,控制 webpack 何時(shí)生成性能提示 默認(rèn)值 250000 bytes
maxAssetSize: 100000, // 根據(jù)單個(gè)資源體積,控制 webpack 何時(shí)生成性能提示
assetFilter: function(assetFilename) { // 只給出 .js 文件的性能提示褪猛。
return assetFilename.endsWith('.js');
}
}
}
12. Stats
stats: "minimal", // string enum 只在發(fā)生錯(cuò)誤或有新的編譯時(shí)輸出
stats: {}, // 使用對(duì)象對(duì)統(tǒng)計(jì)信息 進(jìn)行更精確的控制
至此 网杆,文檔中的概念,配置,Loaders碳却, plugins 已完成概覽队秩。接下來(lái)抽空完成,實(shí)戰(zhàn)昼浦, 優(yōu)化馍资, 原理。