炒冷飯系列 -- 10 分鐘搞定 file-loader

原文地址javascript

什麼是 file-loader

簡單來講,file-loader 就是在 JavaScript 代碼裏 import/require 一個文件時,會將該文件生成到輸出目錄,而且在 JavaScript 代碼裏返回該文件的地址。java

如何使用

1. 安裝 file-loader

npm install file-loader --save-dev

2. 配置 webapck

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {},
          },
        ],
      },
    ],
  },
};

關於 file-loaderoptions,這裏就很少說了,見 file-loader options .node

3. 引入一個文件,能夠是 import(或 require

import logo from '../assets/image/logo.png';
console.log('logo的值: ', logo); // 打印一下看看 logo 是什麼

簡單三步就搞定了。webpack

4. 見證奇蹟的時刻

webpack

執行 webpack 打包以後,dist 目錄下會生成一個打包好的 bundle.js,這個就很少說了。git

若是使用了 file-loaderdist 目錄這時候會生成咱們用到的那個文件,在這裏也就是 logo.pnggithub

默認狀況下,生成到 dist 目錄的文件不會是原文件名,而是:**[原文件內容的 MD5 哈希值].[原文件擴展名]**web

回到上文,console.log(logo) 會打印什麼呢,咱們執 bundle.js 看看:npm

node dist/bundle.js

輸出結果是:json

logo的值:  dab1fd6b179f2dd87254d6e0f9f8efab.png

如上所說,會返回文件的地址。api

源碼解析

file-loader 的代碼很少,就直接貼在這了:

import path from 'path';

import loaderUtils from 'loader-utils'; // loader 工具包
import validateOptions from 'schema-utils'; // schema 工具包

import schema from './options.json'; // options schema

export default function loader(content) {
  // 獲取 webpack 配置裏的 options
  const options = loaderUtils.getOptions(this) || {};

  // 校驗 options
  validateOptions(schema, options, {
    name: 'File Loader',
    baseDataPath: 'options',
  });

  // 獲取 context
  const context = options.context || this.rootContext;

  // 根據 name 配置和 content 內容生成一個文件名
  // 默認是 [contenthash].[ext],也就是根據 content 的 hash 來生成文件名
  const url = loaderUtils.interpolateName(
    this,
    options.name || '[contenthash].[ext]',
    {
      context,
      content,
      regExp: options.regExp,
    }
  );

  let outputPath = url;

  // 若是配置了 outputPath,則須要作一些拼接操做
  if (options.outputPath) {
    if (typeof options.outputPath === 'function') {
      outputPath = options.outputPath(url, this.resourcePath, context);
    } else {
      outputPath = path.posix.join(options.outputPath, url);
    }
  }

  // __webpack_public_path__ 是 webpack 定義的全局變量,是 output.publicPath 的值
  let publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`;

  // 一樣,若是配置了 publicPath,則須要作一些拼接操做
  if (options.publicPath) {
    if (typeof options.publicPath === 'function') {
      publicPath = options.publicPath(url, this.resourcePath, context);
    } else {
      publicPath = `${
        options.publicPath.endsWith('/')
          ? options.publicPath
          : `${options.publicPath}/`
      }${url}`;
    }
    publicPath = JSON.stringify(publicPath);
  }

  // 關於 postTransformPublicPath,能夠看一下 https://webpack.js.org/loaders/file-loader/#posttransformpublicpath
  if (options.postTransformPublicPath) {
    publicPath = options.postTransformPublicPath(publicPath);
  }

  if (typeof options.emitFile === 'undefined' || options.emitFile) {
    // 讓 webpack 生成一個文件
    this.emitFile(outputPath, content);
  }

  // TODO revert to ES2015 Module export, when new CSS Pipeline is in place
  // 這裏能夠思考一下爲何返回的是 `module.exports = ${publicPath};`,而不是 publicPath
  return `module.exports = ${publicPath};`;
}

// 默認狀況下 webpack 對文件進行 UTF8 編碼,當 loader 須要處理二進制數據的時候,須要設置 raw 爲 true
export const raw = true;

參考

相關文章
相關標籤/搜索