1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        字節(jié)面試官:談?wù)刦ile-loader和url-loader的區(qū)別,能不能手寫(xiě)出來(lái)?

        共 5316字,需瀏覽 11分鐘

         ·

        2021-08-02 16:09


        什么是 url-loader

        url-loader 會(huì)將引入的文件進(jìn)行編碼,生成 DataURL,相當(dāng)于把文件翻譯成了一串字符串,再把這個(gè)字符串打包到 JavaScript。

        使用 base64 來(lái)加載圖片也是有兩面性的:

        • 優(yōu)點(diǎn):節(jié)省請(qǐng)求,提高頁(yè)面性能
        • 缺點(diǎn):增大本地文件大小,降低加載性能

        所以我們得有取舍,只對(duì)部分小 size 的圖片進(jìn)行 base64 編碼,其它的大圖片還是發(fā)請(qǐng)求吧。

        什么是 file-loader

        在css文件中定義background的屬性或者在html中引入image的src,我們知道在webpack打包后這些圖片會(huì)打包至定義好的一個(gè)文件夾下,和開(kāi)發(fā)時(shí)候的相對(duì)路徑會(huì)不一樣,這就會(huì)導(dǎo)致導(dǎo)入圖片路徑的錯(cuò)誤。而file-loader正是為了解決此類(lèi)問(wèn)題而產(chǎn)生的,他修改打包后圖片的儲(chǔ)存路徑,再根據(jù)配置修改我們引用的路徑,使之對(duì)應(yīng)引入

        之間有什么聯(lián)系呢?

        url-loader內(nèi)部封裝了file-loader。url-loader不依賴(lài)于file-loader,即使用url-loader時(shí),只需要安裝url-loader即可,不需要安裝file-loader。

        通過(guò)上面的介紹,我們可以看到,url-loader工作分兩種情況:

        1. 文件大小小于limit參數(shù),url-loader將會(huì)把文件轉(zhuǎn)為DataURL;
        2. 文件大小大于limit,url-loader會(huì)調(diào)用file-loader進(jìn)行處理,參數(shù)也會(huì)直接傳給file-loader。因此我們只需要安裝url-loader即可

        手寫(xiě)實(shí)現(xiàn)file-loader

        file-loader 的工作流程如下

        • 通過(guò) loaderUtils.interpolateName 方法可以根據(jù) options.name 以及文件內(nèi)容生成一個(gè)唯一的文件名 url(一般配置都會(huì)帶上hash,否則很可能由于文件重名而沖突)

        • 通過(guò) this.emitFile(url, content) 告訴 webpack 我需要?jiǎng)?chuàng)建一個(gè)文件,webpack會(huì)根據(jù)參數(shù)創(chuàng)建對(duì)應(yīng)的文件,放在 public path 目錄下。

        • 返回 'module.exports = webpack_public_path + '+ JSON.stringify(url) + ‘;’ ,這樣就會(huì)把原來(lái)的文件路徑替換為編譯后的路徑

        對(duì)file-loader 中最重要的幾行代碼解釋如下(我們自己來(lái)實(shí)現(xiàn)一個(gè) file-loader 就只需要這幾行代碼就行了,完全可以正常運(yùn)行且支持 name 配置):

        var loaderUtils = require('loader-utils')

        module.exports = function (content{

          // 獲取options,就是 webpack 中對(duì) file-loader 的配置,比如這里我們配置的是 `name=[name]_[hash].[ext]`
          // 獲取到的就是這樣一個(gè)k-v 對(duì)象 { name: "[name]_[hash].[ext]" }
          const options = loaderUtils.getOptions(this) || {};

          // 這是 loaderUtils 的一個(gè)方法,可以根據(jù) name 配置和 content 內(nèi)容 生成一個(gè)文件名。為什么需要 文件內(nèi)容呢?這是為了保證當(dāng)文件內(nèi)容沒(méi)有發(fā)生變化的時(shí)候,名字中的 [hash] 字段也不會(huì)變??梢岳斫鉃橛梦募膬?nèi)容作了一個(gè)hash
          let url = loaderUtils.interpolateName(this, options.name, {
            content
          })

          this.emitFile(url, content) // 告訴webpack,我要?jiǎng)?chuàng)建一個(gè)文件,文件名和內(nèi)容,這樣webpack就會(huì)幫你在 dist 目錄下創(chuàng)建一個(gè)對(duì)應(yīng)的文件

          // 這里要用到一個(gè)變量,就是 __webpack_public_path__ ,這是一個(gè)由webpack提供的全局變量,是public的根路徑
          // 參見(jiàn):https://webpack.js.org/guides/public-path/#on-the-fly
          // 這里要注意一點(diǎn):這個(gè)返回的字符串是一段JS,顯然,他是在瀏覽器中運(yùn)行的
          // 舉個(gè)栗子:
          // css源碼這樣寫(xiě):background-image: url('a.png')
          // 編譯后變成: background-image: require('xxxxxx.png')
          // 這里的 require 語(yǔ)句返回的結(jié)果,就是下面的 exports 的字符串,也就是圖片的路徑
          return 'module.exports = __webpack_public_path__ + 'JSON.stringify(url)
        }

        // 一定別忘了這個(gè),因?yàn)槟J(rèn)情況下 webpack 會(huì)把文件內(nèi)容當(dāng)做UTF8字符串處理,而我們的文件是二進(jìn)制的,當(dāng)做UTF8會(huì)導(dǎo)致圖片格式錯(cuò)誤。
        // 因此我們需要指定webpack用 raw-loader 來(lái)加載文件的內(nèi)容,而不是當(dāng)做 UTF8 字符串傳給我們
        module.exports.raw = true

        手寫(xiě)url-loader

        url-loader 的工作流程如下:

        • 獲取 limit 參數(shù)
        • 如果 文件大小在 limit 之類(lèi),則直接返回文件的 base64 編碼后內(nèi)容
        • 如果超過(guò)了 limit ,則調(diào)用 file-loader
        • 因?yàn)檫壿嫳容^簡(jiǎn)單,這里直接放上源碼以及我添加的注釋?zhuān)?/section>
        module.exports = function(content{

            // 獲取 options 配置,上面已經(jīng)講過(guò)了就不在重復(fù)
          var options =  loaderUtils.getOptions(this) || {};
          // Options `dataUrlLimit` is backward compatibility with first loader versions
            // limit 參數(shù),只有文件大小小于這個(gè)數(shù)值的時(shí)候我們才進(jìn)行base64編碼,否則將直接調(diào)用 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 編碼的內(nèi)容
            return "module.exports = " + JSON.stringify("data:" + (mimetype ? mimetype + ";" : "") + "base64," + content.toString("base64"));
          }

            // 超過(guò)了文件大小限制,那么我們將直接調(diào)用 file-loader 來(lái)加載
          var fallback = options.fallback || "file-loader";
          var fallbackLoader = require(fallback);

          return fallbackLoader.call(this, content);
        }



        // 一定別忘了這個(gè),因?yàn)槟J(rèn)情況下 webpack 會(huì)把文件內(nèi)容當(dāng)做UTF8字符串處理,而我們的文件是二進(jìn)制的,當(dāng)做UTF8會(huì)導(dǎo)致圖片格式錯(cuò)誤。
        // 因此我們需要指定webpack用 raw-loader 來(lái)加載文件的內(nèi)容,而不是當(dāng)做 UTF8 字符串傳給我們
        // 參見(jiàn):https://webpack.github.io/docs/loaders.html#raw-loader
        module.exports.raw = true

        總結(jié)

        • file-loader 返回的是文件的路徑
        • url-loader 返回的是文件的base64編碼

        參考文獻(xiàn)

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


        • 最后

        • 歡迎關(guān)注 《前端陽(yáng)光》公眾號(hào),發(fā)送加群,可加入技術(shù)交流群和各大廠內(nèi)推群,也可以回復(fù)內(nèi)推碼,獲得各大廠內(nèi)推碼。

        瀏覽 61
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            男女大鸡巴激情免费黄色视频网站 | 一区不卡| 久久A级片 | 操比网站在线观看 | 黑人洋妞大混交视频 | 日韩一区国产 | 国产特级全黄一级97毛片 | 亚洲欧美激情小说另类 | 国产精品高清尿小便嘘嘘剧情介绍 | 中文字幕人妻熟女一区二区三区电影 |