<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          字節(jié)面試官:談?wù)刦ile-loader和url-loader的區(qū)別,能不能手寫出來(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è)文件夾下,和開發(fā)時(shí)候的相對(duì)路徑會(huì)不一樣,這就會(huì)導(dǎo)致導(dǎo)入圖片路徑的錯(cuò)誤。而file-loader正是為了解決此類問(wèn)題而產(chǎn)生的,他修改打包后圖片的儲(chǔ)存路徑,再根據(jù)配置修改我們引用的路徑,使之對(duì)應(yīng)引入

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

          url-loader內(nèi)部封裝了file-loader。url-loader不依賴于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即可

          手寫實(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源碼這樣寫: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

          手寫url-loader

          url-loader 的工作流程如下:

          • 獲取 limit 參數(shù)
          • 如果 文件大小在 limit 之類,則直接返回文件的 base64 編碼后內(nèi)容
          • 如果超過(guò)了 limit ,則調(diào)用 file-loader
          • 因?yàn)檫壿嫳容^簡(jiǎn)單,這里直接放上源碼以及我添加的注釋:
          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)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天综合网~永久入口红桃 | 国产精品人人妻人人爽人人牛 | 国产精品粉嫩在线播放 | 久久一色一 | 大香蕉伊人丁香五月 |