這篇文章主要為大家展示了“Webpack loader之file-loader怎么用”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Webpack loader之file-loader怎么用”這篇文章吧。
創(chuàng)新互聯(lián)建站是一家專注于做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),永濟(jì)網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:永濟(jì)等地區(qū)。永濟(jì)做網(wǎng)站價(jià)格咨詢:18980820575
簡介
安裝
npm install --save-dev file-loader
用法
默認(rèn)情況下,生成的文件的文件名就是文件內(nèi)容的 MD5 哈希值并會(huì)保留所引用資源的原始擴(kuò)展名。
import img from './webpack-logo.png'
webpack.config.js
module.exports = { module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: {} } ] } ] } }
生成文件 bd62c377ad80f89061ea5ad8829df35b.png
(默認(rèn)的文件名為 [hash].[ext]),輸出到輸出目錄并返回 public URL。
"/public/path/bd62c377ad80f89061ea5ad8829df35b.png"
當(dāng)然如果不想使用默認(rèn)的文件名,我們也可以通過配置 options.name
選項(xiàng)來設(shè)置輸出的文件名命名規(guī)則,需要注意的是 name 選項(xiàng)支持的類型為: {String|Function}
:
String 類型
webpack.config.js
{ loader: 'file-loader', options: { name: '[path][name].[ext]' } }
Function 類型
webpack.config.js
{ loader: 'file-loader', options: { name (file) { if (env === 'development') { return '[path][name].[ext]' } return '[hash].[ext]' } } }
以上的示例中,我們使用了 [path]
, [name]
, [hash]
和 [ext]
占位符,它們對(duì)應(yīng)的含義是:
[ext]:String,默認(rèn)值為 file.extname,表示資源擴(kuò)展名;
[name]:String,默認(rèn)值為 file.basename,表示資源的基本名稱;
[path]:String,默認(rèn)值為 file.dirname,表示資源相對(duì)于 context 的路徑;
[hash]:String,默認(rèn)值為 md5,內(nèi)容的哈希值,支持靈活的 hashes 配置,配置規(guī)則為:[
其實(shí)除了以上常用的四個(gè)占位符之外,還有支持 [N]
,N 是數(shù)值類型,表示當(dāng)前文件名按照查詢參數(shù) regExp
匹配后獲得到第 N 個(gè)匹配結(jié)果。介紹完 name 配置項(xiàng),接下來我們來繼續(xù)介紹幾個(gè)常用的配置。
常用配置項(xiàng) outputPath
outputPath 用于配置自定義 output
輸出目錄,支持 String|Function 類型,默認(rèn)值為 ‘undefined',用法如下:
webpack.config.js
{ loader: 'file-loader', options: { name: '[path][name].[ext]', outputPath: 'images/' } }
需要注意的是,outputPath 所設(shè)置的路徑,是相對(duì)于 webpack 的輸出目錄。
publicPath
publicPath 用于配置自定義 public
發(fā)布目錄,支持 String|Function 類型,默認(rèn)值為 __webpack_public__path__
,用法如下:
webpack.config.js
{ loader: 'file-loader', options: { name: '[path][name].[ext]', publicPath: 'assets/' } }
emitFile
emitFile 用于設(shè)置是否生成文件,類型是 Boolean,默認(rèn)值為 true。但我們可以通過將 emitFile 設(shè)置為 false 來禁用該默認(rèn)行為。
webpack.config.js
{ loader: 'file-loader', options: { emitFile: false } }
outputPath vs publicPath
outputPath 僅僅告訴 webpack 結(jié)果存儲(chǔ)在哪里,然而 publicPath 選項(xiàng)則被許多 webpack 的插件用于在生產(chǎn)模式下更新內(nèi)嵌到 css、html 文件內(nèi)的 url 值。例如:
// Development: Both Server and the image are on localhost .image { background-image: url('./test.png'); } // Production: Server is on Heroku but the image is on a cdn .image { background-image: url('https://some-cdn/test.png'); }
loader 準(zhǔn)則
編寫 loader 時(shí)應(yīng)該遵循以下準(zhǔn)則:
簡單易用。
使用鏈?zhǔn)絺鬟f。
模塊化的輸出。
確保無狀態(tài)。
使用 loader utilities。
記錄 loader 的依賴。
解析模塊依賴關(guān)系。
提取通用代碼。
避免絕對(duì)路徑。
使用 peer dependencies。
以上的準(zhǔn)則按重要程度排序,但某些僅適用于某些場景。若想進(jìn)一步了解自定義 loader,可以閱讀 編寫一個(gè) loader 這個(gè)文檔。接下來,我們來基于上述的準(zhǔn)則分析一下 file-loader 的源碼。
file-loader 源碼簡析
所謂 loader 只是一個(gè)導(dǎo)出為函數(shù)對(duì)象的 JavaScript 模塊。 loader runner 會(huì)調(diào)用這個(gè)函數(shù),然后把上一個(gè) loader 產(chǎn)生的結(jié)果或者資源文件傳入進(jìn)去。 函數(shù)的 this
上下文將由 webpack 填充,并且 loader runner 具有一些有用方法,可以使 loader 改變?yōu)楫惒秸{(diào)用方式,或者獲取 query 參數(shù) 。
其實(shí)本文介紹的 file-loader 并不會(huì)對(duì)文件的內(nèi)容進(jìn)行任何轉(zhuǎn)換,只是復(fù)制一份文件內(nèi)容,并根據(jù)相關(guān)的配置生成對(duì)應(yīng)的文件名,所生成的文件名一般會(huì)帶上 hash 值,從而避免文件重名導(dǎo)致沖突。接下來我們來簡單分析一下 file-loader 的部分源碼。
導(dǎo)入依賴模塊
import path from 'path'; import loaderUtils from 'loader-utils'; import validateOptions from 'schema-utils'; import schema from './options.json';
獲取配置對(duì)象及驗(yàn)證
export default function loader(content) { if (!this.emitFile) throw new Error('File Loader\n\nemitFile is required from module system'); const options = loaderUtils.getOptions(this) || {}; validateOptions(schema, options, 'File Loader'); }
以上代碼中,emitFile 是由 loader 上下文提供的方法,用于輸出一個(gè)文件,對(duì)應(yīng)的函數(shù)簽名如下:
emitFile(name: string, content: Buffer|string, sourceMap: {...})
在調(diào)用 file-loader 時(shí),如果發(fā)現(xiàn) this.emitFile 無效,則會(huì)拋出異常。接著 file-loader 會(huì)先調(diào)用 loaderUtils.getOptions() 方法,獲取當(dāng)前 loader 對(duì)應(yīng)的配置對(duì)象,然后基于已定義的 Schema,驗(yàn)證配置對(duì)象的有效性。對(duì)應(yīng)的 Schema 定義如下(不包含異常提示信息):
{ "type": "object", "properties": { "name": {}, "regExp": {}, "context": { "type": "string" }, "publicPath": {}, "outputPath": {}, "useRelativePath": { "type": "boolean" }, "emitFile": { "type": "boolean" } }, "additionalProperties": true }
獲取 context 及生成文件名稱
const context = options.context //自定義文件context // 從webpack 4開始,原先的this.options.context // 被改進(jìn)為this.rootContext || this.rootContext || (this.options && this.options.context); const url = loaderUtils.interpolateName( this, options.name, // 默認(rèn)為"[hash].[ext]" { context, content, regExp: options.regExp, });
loaderUtils 中的 interpolateName 方法,用于生成對(duì)應(yīng)的文件名,該方法的簽名如下:
interpolateName(loaderContext, name, options);
其中 loaderContext 為 loader 的上下文對(duì)象,name 為文件名稱模板,options 為配置對(duì)象,支持 context,content 和 regExp 屬性。該方法的使用示例如下:
示例一:
// loaderContext.resourcePath = "/app/js/javascript.js"; let interpolatedName = loaderUtils.interpolateName( loaderContext, "js/[hash].script.[ext]", { content: "console.log('loaderUtils')" }); // => js/e353f4da4c3e380646d2b4d75c8a13ab.script.js
以上示例核心的處理流程如下:
示例二:
// loaderContext.resourcePath = "/app/js/page-home.js" loaderUtils.interpolateName( loaderContext, "script-[1].[ext]", { regExp: "page-(.*)\\.js", content: "console.log('loaderUtils')" }); // => script-home.js
處理 outputPath
let outputPath = url; if (options.outputPath) { if (typeof options.outputPath === 'function') { outputPath = options.outputPath(url); } else { outputPath = path.posix.join(options.outputPath, url); } }
處理 publicPath
// __webpack_require__.p = ""; let publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`; if (options.publicPath) { if (typeof options.publicPath === 'function') { publicPath = options.publicPath(url); } else if (options.publicPath.endsWith('/')) { publicPath = options.publicPath + url; } else { publicPath = `${options.publicPath}/${url}`; } publicPath = JSON.stringify(publicPath); }
處理 emitFile
if (options.emitFile === undefined || options.emitFile) { // 把文件輸出到指定的outputPath路徑 this.emitFile(outputPath, content); }
導(dǎo)出最終路徑
return `module.exports = ${publicPath};`;
以上是“Webpack loader之file-loader怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!