zoukankan      html  css  js  c++  java
  • file-loader和url-loader的区别

    什么是 url-loader

    url-loader 会将引入的文件进行编码,生成 DataURL,相当于把文件翻译成了一串字符串,再把这个字符串打包到 JavaScript。

    使用 base64 来加载图片也是有两面性的:

    • 优点:节省请求,提高页面性能
    • 缺点:增大本地文件大小,降低加载性能

    所以我们得有取舍,只对部分小 size 的图片进行 base64 编码,其它的大图片还是发请求吧。

    什么是 file-loader

    在css文件中定义background的属性或者在html中引入image的src,我们知道在webpack打包后这些图片会打包至定义好的一个文件夹下,和开发时候的相对路径会不一样,这就会导致导入图片路径的错误。而file-loader正是为了解决此类问题而产生的,他修改打包后图片的储存路径,再根据配置修改我们引用的路径,使之对应引入

    之间有什么联系呢?

    url-loader内部封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader。

    通过上面的介绍,我们可以看到,url-loader工作分两种情况:

    1. 文件大小小于limit参数,url-loader将会把文件转为DataURL;
    2. 文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。因此我们只需要安装url-loader即可

    手写实现file-loader

    file-loader 的工作流程如下:

    • 通过 loaderUtils.interpolateName 方法可以根据 options.name 以及文件内容生成一个唯一的文件名 url(一般配置都会带上hash,否则很可能由于文件重名而冲突)

    • 通过 this.emitFile(url, content) 告诉 webpack 我需要创建一个文件,webpack会根据参数创建对应的文件,放在 public path 目录下。

    • 返回 'module.exports = webpack_public_path + '+ JSON.stringify(url) + ‘;’ ,这样就会把原来的文件路径替换为编译后的路径

    对file-loader 中最重要的几行代码解释如下(我们自己来实现一个 file-loader 就只需要这几行代码就行了,完全可以正常运行且支持 name 配置):

    var loaderUtils = require('loader-utils')

    module.exports = function (content) {

      // 获取options,就是 webpack 中对 file-loader 的配置,比如这里我们配置的是 `name=[name]_[hash].[ext]`
      // 获取到的就是这样一个k-v 对象 { name: "[name]_[hash].[ext]" }
      const options = loaderUtils.getOptions(this) || {};

      // 这是 loaderUtils 的一个方法,可以根据 name 配置和 content 内容 生成一个文件名。为什么需要 文件内容呢?这是为了保证当文件内容没有发生变化的时候,名字中的 [hash] 字段也不会变。可以理解为用文件的内容作了一个hash
      let url = loaderUtils.interpolateName(this, options.name, {
        content
      })

      this.emitFile(url, content) // 告诉webpack,我要创建一个文件,文件名和内容,这样webpack就会帮你在 dist 目录下创建一个对应的文件

      // 这里要用到一个变量,就是 __webpack_public_path__ ,这是一个由webpack提供的全局变量,是public的根路径
      // 参见:https://webpack.js.org/guides/public-path/#on-the-fly
      // 这里要注意一点:这个返回的字符串是一段JS,显然,他是在浏览器中运行的
      // 举个栗子:
      // css源码这样写:background-image: url('a.png')
      // 编译后变成: background-image: require('xxxxxx.png')
      // 这里的 require 语句返回的结果,就是下面的 exports 的字符串,也就是图片的路径
      return 'module.exports = __webpack_public_path__ + '+ JSON.stringify(url)
    }

    // 一定别忘了这个,因为默认情况下 webpack 会把文件内容当做UTF8字符串处理,而我们的文件是二进制的,当做UTF8会导致图片格式错误。
    // 因此我们需要指定webpack用 raw-loader 来加载文件的内容,而不是当做 UTF8 字符串传给我们
    module.exports.raw = true

    手写url-loader

    url-loader 的工作流程如下:

    • 获取 limit 参数
    • 如果 文件大小在 limit 之类,则直接返回文件的 base64 编码后内容
    • 如果超过了 limit ,则调用 file-loader
    • 因为逻辑比较简单,这里直接放上源码以及我添加的注释:
    module.exports = function(content) {

        // 获取 options 配置,上面已经讲过了就不在重复
      var options =  loaderUtils.getOptions(this) || {};
      // Options `dataUrlLimit` is backward compatibility with first loader versions
        // limit 参数,只有文件大小小于这个数值的时候我们才进行base64编码,否则将直接调用 file-loader
      var limit = options.limit || (this.options && this.options.url && this.options.url.dataUrlLimit);

      if(limit) {
        limit = parseInt(limit, 10);
      }

      var mimetype = options.mimetype || options.minetype || mime.lookup(this.resourcePath);

      // No limits or limit more than content length
      if(!limit || content.length < limit) {
        if(typeof content === "string") {
          content = new Buffer(content);
        }

            // 直接返回 base64 编码的内容
        return "module.exports = " + JSON.stringify("data:" + (mimetype ? mimetype + ";" : "") + "base64," + content.toString("base64"));
      }

        // 超过了文件大小限制,那么我们将直接调用 file-loader 来加载
      var fallback = options.fallback || "file-loader";
      var fallbackLoader = require(fallback);

      return fallbackLoader.call(this, content);
    }



    // 一定别忘了这个,因为默认情况下 webpack 会把文件内容当做UTF8字符串处理,而我们的文件是二进制的,当做UTF8会导致图片格式错误。
    // 因此我们需要指定webpack用 raw-loader 来加载文件的内容,而不是当做 UTF8 字符串传给我们
    // 参见:https://webpack.github.io/docs/loaders.html#raw-loader
    module.exports.raw = true

    总结

    • file-loader 返回的是文件的路径
    • url-loader 返回的是文件的base64编码

    参考文献

    • 详解webpack url-loader和file-loader:https://segmentfault.com/a/1190000018987483
    • webpack 源码解析:file-loader 和 url-loader:https://www.cnblogs.com/shiyunfront/articles/8944940.html

     

    欢迎关注前端早茶,与广东靓仔携手共同进阶

    前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~

    公众号作者:广东靓仔

  • 相关阅读:
    六大设计原则(一)
    .Net MVC 实现WebSocket
    Socket基础三
    Linux date命令的用法(转)
    SpringBoot自定义校验注解校验日期时间格式字符串
    前缀、中缀、后缀表达式
    什么是重放攻击,列举几种常见防御手段?
    09月13日总结
    09月12日总结
    09月11日总结
  • 原文地址:https://www.cnblogs.com/cczlovexw/p/15097383.html
Copyright © 2011-2022 走看看