你們好,以前出了一篇面試篇webpack入門,這篇文章繼續介紹接下來更深刻東西。javascript
講道理你們都是直接import一個loader或者使用webpack內置的loader的。css
若是調試本身的loader,應該以下寫法:vue
//webpack.config.js
const path = require("path");
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve("loader.js"),
options: {
test: 'apple'
}
}
]
}
]
}
};
複製代碼
其實和正常載入loader同樣,只是這裏指向的是本地文件的路徑。java
path.resolve('loader.js') 得出路徑node
/Users/kev1nzh/Desktop/my/webpack/loader.jsreact
在使用一個loader的時候,loader會接收你正則匹配的資源文件(如上,全部js文件)的字符串。
loader經過代碼轉化模塊後,最後返回傳遞出去。
複製代碼
當使用多個loader的時候,從傳入loader數組的最後一個開始反向傳入資源文件字符串。webpack
最後一個loader接收最原始的資源文件字符串,轉化後傳入下一個lodaer。ios
中間的loader接收上一個loader,轉化後傳入下一個。es6
第一個loader最後接收轉化,並傳出全部loader處理完的資源文件字符串。web
{
test: /\.css$/,
use: [
{
loader: 'css-loader'
},
{
loader: 'style-loader'
},
]
}
//style-loader接收全部css的文件,轉化完再傳給css-loader,轉化完後再懟出來。
複製代碼
loader-utils, schema-utils是webpack的loader工具庫,有不少便捷的方法能夠調用。
const { getOptions,stringifyRequest, parseQuery } = require("loader-utils");
const validateOptions = require("schema-utils");
const schema = {
type: "object",
properties: {
test: {
type: "string"
}
}
};
module.exports = function(source) {
//getOptions 用於在loader裏獲取傳入的options,返回的是對象值。
const options = getOptions(this);
// stringifyRequest轉換路徑,避免require()或impot時使用的絕對路徑
stringifyRequest(this, "./test.js"); // Result => "\"./test.js\""
//parseQuery獲取query參數的,這個很簡單就不說啦
parseQuery('?name=kev&age=14') // Result => {name: 'kev', age: '14'}
//驗證參數的類型是否正確。
validateOptions(schema, options, "loader");
};
複製代碼
總算到手寫環節了!!!!
//webapck.config.js
const path = require("path");
module.exports = {
entry: "./src",
output: {
path: path.resolve(__dirname, "dist"),
filename: "package.js"
},
mode: "production",
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve("loader.js"),
options: {
work: '996',
sick: 'ICU',
}
}
]
}
]
}
};
複製代碼
首先載入工具庫,爲了後續使用。
第一步先驗證options是否符合類型,
第二步獲取參數,而後替換傳入的資源文件字符串。
//loader.js
const { getOptions } = require("loader-utils");
const validateOptions = require("schema-utils");
const schema = {
type: "object",
properties: {
work: {
type: 'String'
},
sick: {
type: 'String'
}
}
};
module.exports = function(source) {
const options = getOptions(this);
validateOptions(schema, options, 'loader');
const {work, sick} = options;
source = source.replace(/\[work\]/g, work).replace(/\[sick\]/g, sick);
return `export default ${JSON.stringify(source)}`;
};
複製代碼
展現下要轉換的js。
// src/index.js
console.log('工做[work] 生病[sick] 加班不規範 親人兩行淚');
複製代碼
最後在命令行,webpack!!!!!
const index = require('./index');
const console = require('./console');
//index.js
const axios = require('./scripts/debounce.js'');
const moment = require('moment');
// do something
複製代碼
// ./src/moment.js
const moment = require('moment');
console.log(moment().format('MMMM Do YYYY, h:mm:ss a'))
// ./index.js
const momentJs = require('./src/moment');
console.log(123);
複製代碼
如上代碼,咱們打包一下試試看。
兩個文件有依賴關係,因此打包後,都會把moment模塊打包進去。webpack4.x的分離代碼方法,以前的CommonsChunkPlugin插件已被移除。 此模塊開箱即用,默認狀況下,它僅影響按需塊,由於更改初始塊會影響HTML文件應包含的腳本標記以運行項目。
webpack將根據如下條件自動拆分塊:
讓咱們看下代碼如何實現!
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'initial', //選擇哪些模塊須要優化, 參數爲 all、async、initial
minSize: 30000, // 要生成的塊的最小數
maxSize: 0, //要生成的塊的最大數
minChunks: 2, // 分割前共享模塊的最小塊數
maxAsyncRequests: 5, //按需加載時的最大並行請求數
maxInitialRequests: 3, // 入口的最大並行請求數
automaticNameDelimiter: '~', //指定生成文件名當中的分隔符
name: true, //拆分塊的名稱
cacheGroups: { //緩存組
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
複製代碼
面試系列第一篇: 面試官:你知道Callback Hell(回調地獄)嗎?
面試系列第二篇: 面試官:react和vue有什麼區別嗎?
面試系列第三篇: 面試官:你瞭解es6的知識嗎?
面試系列第四篇: 面試官:你瞭解Webpack嗎?