详解Webpack loader 之 file(2)

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 上下文提供的方法,用于输出一个文件,对应的函数签名如下:

emitFile(name: string, content: Buffer|string, sourceMap: {...})

在调用 file-loader 时,如果发现 this.emitFile 无效,则会抛出异常。接着 file-loader 会先调用 loaderUtils.getOptions() 方法,获取当前 loader 对应的配置对象,然后基于已定义的 Schema,验证配置对象的有效性。对应的 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 // 被改进为this.rootContext || this.rootContext || (this.options && this.options.context); const url = loaderUtils.interpolateName( this, options.name, // 默认为"[hash].[ext]" { context, content, regExp: options.regExp, });

loaderUtils 中的 interpolateName 方法,用于生成对应的文件名,该方法的签名如下:

interpolateName(loaderContext, name, options);

其中 loaderContext 为 loader 的上下文对象,name 为文件名称模板,options 为配置对象,支持 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

以上示例核心的处理流程如下:

详解Webpack loader 之 file

示例二:

// 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('https://www.jb51.net/')) { 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); }

导出最终路径

return `module.exports = ${publicPath};`;

参考资源

loader API
webpack-the-confusing-parts

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/4272b3f64001582c0e52bdcebf0415f6.html