webpack(個(gè)人筆記)

webpack官網(wǎng):https://webpack.js.org/
webpack中文文檔: https://www.webpackjs.com/concepts/

image.png

1.什么是webpack

概念:本質(zhì)上,webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時(shí),它會(huì)遞歸地構(gòu)建一個(gè)依賴(lài)關(guān)系圖(dependency graph),其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle。

簡(jiǎn)單理解:webpack是一個(gè)打包模塊化javascript的工具,在webpack里一切文件皆模塊,通過(guò)loader轉(zhuǎn)換文件,通過(guò)plugin注入鉤子,最后輸出由多個(gè)模塊組合成的文件,webpack專(zhuān)注構(gòu)建模塊化項(xiàng)目。
WebPack可以看做是模塊打包機(jī):它做的事情是,分析你的項(xiàng)目結(jié)構(gòu),找到JavaScript模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。

2.基本使用

webpack基本使用

基本使用.png
配置入口與出口.png

自動(dòng)打包.png

生成直接預(yù)覽頁(yè)面.png

配置完訪問(wèn)localhost:8080可以直接訪問(wèn)頁(yè)面(不配置的話訪問(wèn)看到的頁(yè)面是項(xiàng)目目錄,然后再點(diǎn)擊進(jìn)去訪問(wèn))


打包完自動(dòng)打開(kāi)頁(yè)面.png

配置完運(yùn)行npm run dev打包之后可以直接打開(kāi)頁(yè)面,不用再?gòu)?fù)制訪問(wèn)地址。

webapck的加載器loader

loader加載器1.png

沒(méi)有l(wèi)oader加載器打包c(diǎn)ss文件報(bào)錯(cuò):

沒(méi)有l(wèi)oader加載器報(bào)錯(cuò).png

基本使用:

loader加載器基本使用1.png
less-loader.png
sass-loader.png
處理css兼容問(wèn)題.png
url-loader.png

webpack默認(rèn)不打包樣式表中的圖片,如css文件中的背景圖片的url。所以需要借助url-loader來(lái)進(jìn)行打包,否則會(huì)報(bào)錯(cuò)。

打包js高級(jí)語(yǔ)法.png

幾個(gè)常見(jiàn)的loader

  • file-loader:把文件輸出到一個(gè)文件夾中,在代碼中通過(guò)相對(duì) URL 去引用輸出的文件

  • url-loader:和 file-loader 類(lèi)似,但是能在文件很小的情況下以 base64 的方式把文件內(nèi)容注入到代碼中去

  • source-map-loader:加載額外的 Source Map 文件,以方便斷點(diǎn)調(diào)試

  • image-loader:加載并且壓縮圖片文件

  • babel-loader:把 ES6 轉(zhuǎn)換成 ES5

  • css-loader:加載 CSS,支持模塊化、壓縮、文件導(dǎo)入等特性

  • style-loader:把 CSS 代碼注入到 JavaScript 中,通過(guò) DOM 操作去加載 CSS。

  • eslint-loader:通過(guò) ESLint 檢查 JavaScript 代碼

webpack中的plugin

什么是plugin

plugin是一個(gè)具有 apply方法的 js對(duì)象。 apply方法會(huì)被 webpack的 compiler(編譯器)對(duì)象調(diào)用,并且 compiler 對(duì)象可在整個(gè) compilation(編譯)生命周期內(nèi)訪問(wèn)。

一個(gè)plugin看起來(lái)大概是這個(gè)樣子:

 function CustomPlugin(options){
    // options是配置文件,你可以在這里進(jìn)行一些與options相關(guān)的工作
  }
  ?
  // 每個(gè)plugin都必須定義一個(gè)apply方法,webpack會(huì)自動(dòng)調(diào)用這個(gè)方法
  CustomPlugin.prototype.apply = function(compiler){
      ......
      });
  }
  ?
  module.exports = CustomPlugin;

plugin有什么用

plugin是webpack核心功能,通過(guò)plugin(插件)webpack可以實(shí)現(xiàn)loader所不能完成的復(fù)雜功能,使用plugin豐富的自定義API,可以控制webpack編譯流程的每個(gè)環(huán)節(jié),實(shí)現(xiàn)對(duì)webpack的自定義功能擴(kuò)展。

舉例 我們實(shí)際項(xiàng)目中就使用了HtmlWebpackPlugin插件,它幫助我們做了下面幾件事兒:

  • 在工程打包成功后會(huì)自動(dòng)生成一個(gè)html模板文件

  • 同時(shí)所依賴(lài)的CSS/JS也都會(huì)被自動(dòng)引入到這個(gè)html模板文件中

  • 設(shè)置生成hash添加在引入文件地址的末尾,類(lèi)似于我們常用的時(shí)間戳,來(lái)解決可能會(huì)遇到的緩存問(wèn)題。

使用plugin

在 webpack 配置文件(webpack.config.js)中,向 plugins 屬性傳入 new 實(shí)例即可。比如:

 const HtmlWebpackPlugin = require('html-webpack-plugin');
  const webpack = require('webpack');
  module.exports = {

    module: {
      loaders: [
        {
          test: /\.(js|jsx)$/,
          loader: 'babel-loader'
        }
      ]
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin(), //訪問(wèn)內(nèi)置的插件
      new HtmlWebpackPlugin({template: './src/index.html'}) //訪問(wèn)第三方插件
    ]
  };

注意

  • webpack中的插件分為內(nèi)置插件和第三方插件

  • 內(nèi)置插件不需要額外安裝依賴(lài),如上面的例子中:UglifyJsPlugin插件

  • 如果是第三方插件,如上面的例子中HtmlWebpackPlugin插件,則使用之前需要進(jìn)行安裝:

npm install html-webpack-plugin --save-dev</pre>

幾個(gè)常見(jiàn)的plugin

  • BannerPlugin:對(duì)所有的文件打包后添加一個(gè)版權(quán)聲明

  • uglifyjs-webpack-plugin: 對(duì)JS進(jìn)行壓縮混淆

  • HtmlWebpackPlugin:可以根據(jù)模板自動(dòng)生成html代碼,并自動(dòng)引用css和js文件

  • Hot Module Replacement:在每次修改代碼保存后,瀏覽器會(huì)自動(dòng)刷新,實(shí)時(shí)預(yù)覽修改后的效果

  • copy-webpack-plugin:通過(guò)Webpack來(lái)拷貝文件

  • extract-text-webpack-plugin:將js文件和css文件分別單獨(dú)打包,不混在一個(gè)文件中

  • DefinePlugin 編譯時(shí)配置全局變量,這對(duì)開(kāi)發(fā)模式和發(fā)布模式的構(gòu)建允許不同的變量時(shí)非常有用

  • optimize-css-assets-webpack-plugin 不同組件中重復(fù)的css可以快速去重

  • 更多可點(diǎn)擊這里查看。

3.vue-loader

vue-loader.png
webpack中使用vue.png

4.vue中配置webpack

vue中配置webpack.png

5. 關(guān)閉eslint

在vue.config.js文件中添加一項(xiàng)lintOnSave: false和在devServer項(xiàng)中設(shè)置overlay中的錯(cuò)誤提示為false。

 module.exports = {
    devServer: {
      port: 8081,
      open: true,
      overlay: {
        warnings: false,
        errors: false
    }
    },
    lintOnSave: false
  }

6.webpack優(yōu)缺點(diǎn)

webpack有哪些優(yōu)點(diǎn)

  • 專(zhuān)注于處理模塊化的項(xiàng)目,能做到開(kāi)箱即用,一步到位

  • 可通過(guò)plugin擴(kuò)展,完整好用又不失靈活

  • 使用場(chǎng)景不局限于web開(kāi)發(fā)

  • 社區(qū)龐大活躍,經(jīng)常引入緊跟時(shí)代發(fā)展的新特性,能為大多數(shù)場(chǎng)景找到已有的開(kāi)源擴(kuò)展

  • 良好的開(kāi)發(fā)體驗(yàn)

webpack的缺點(diǎn)

  • webpack的缺點(diǎn)是只能用于采用模塊化開(kāi)發(fā)的項(xiàng)目

7.分別介紹bundle,chunk,module是什么

bundle:是由webpack打包出來(lái)的文件。 chunk:代碼塊,一個(gè)chunk由多個(gè)模塊組合而成,用于代碼的合并和分割。 module:是開(kāi)發(fā)中的單個(gè)模塊,在webpack的世界,一切皆模塊,一個(gè)模塊對(duì)應(yīng)一個(gè)文件,webpack會(huì)從配置的entry中遞歸開(kāi)始找出所有依賴(lài)的模塊。

8.分別介紹什么是loader?什么是plugin

loader:模塊轉(zhuǎn)換器,用于將模塊的原內(nèi)容按照需要轉(zhuǎn)成你想要的內(nèi)容。 plugin:在webpack構(gòu)建流程中的特定時(shí)機(jī)注入擴(kuò)展邏輯,來(lái)改變構(gòu)建結(jié)果,是用來(lái)自定義webpack打包過(guò)程的方式,一個(gè)插件是含有apply方法的一個(gè)對(duì)象,通過(guò)這個(gè)方法可以參與到整個(gè)webpack打包的各個(gè)流程(生命周期)。

9.什么是模塊熱更新

模塊熱更新是webpack的一個(gè)功能,他可以使得代碼修改過(guò)后不用刷新瀏覽器就可以更新,是高級(jí)版的自動(dòng)刷新瀏覽器。 devServer中通過(guò)hot屬性可以空時(shí)模塊的熱替換

1,通過(guò)配置文件

  const webpack = require('webpack');
  const path = require('path');
  let env = process.env.NODE_ENV == "development" ? "development" : "production";
  const config = {
    mode: env,
   devServer: {
       hot:true
   }
  }
    plugins: [
       new webpack.HotModuleReplacementPlugin(), //熱加載插件
    ],
  module.exports = config;</pre>

2,通過(guò)命令行

  "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "start": "NODE_ENV=development  webpack-dev-server --config webpack.develop.config.js --hot",
    }

10.什么是Tree-shaking

Tree-shaking可以用來(lái)剔除javascript中不用的死代碼,它依賴(lài)靜態(tài)的es6模塊化語(yǔ)法,例如通過(guò)哦import 和export 導(dǎo)入導(dǎo)出,Tree-shaking最先在rollup中出現(xiàn),webpack在2.0中將其引入,css中使用Tree-shaking需要引入Purify-CSS。

11.通過(guò)webpack處理長(zhǎng)緩存

瀏覽器在用戶(hù)訪問(wèn)頁(yè)面的時(shí)候,為了加快加載速度,會(huì)對(duì)用戶(hù)訪問(wèn)的靜態(tài)資源進(jìn)行存儲(chǔ),但是每一次代碼升級(jí)或是更新,都需要瀏覽器去下載新的代碼,最方便和簡(jiǎn)單的更新方式就是引入新的文件名稱(chēng)。在webpack中可以在output縱輸出的文件指定chunkhash,并且分離經(jīng)常更新的代碼和框架代碼。通過(guò)NameModulesPlugin或是HashedModuleIdsPlugin使再次打包文件名不變。

12.如何提高webpack的構(gòu)建速度

1. 通過(guò)externals配置來(lái)提取常用庫(kù)

2. 利用DllPlugin和DllReferencePlugin預(yù)編譯資源模塊
通過(guò)DllPlugin來(lái)對(duì)那些我們引用但是絕對(duì)不會(huì)修改的npm包來(lái)進(jìn)行預(yù)編譯,再通過(guò)DllReferencePlugin將預(yù)編譯的模塊加載進(jìn)來(lái)。

3. 使用Happypack 實(shí)現(xiàn)多線程加速編譯

要注意的第一點(diǎn)是,它對(duì)file-loader和url-loader支持不好,所以這兩個(gè)loader就不需要換成happypack了,其他loader可以類(lèi)似地?fù)Q一下

4. 使用Tree-shaking和Scope Hoisting來(lái)剔除多余代碼

5. 使用fast-sass-loader代替sass-loader

6. babel-loader開(kāi)啟緩存

babel-loader在執(zhí)行的時(shí)候,可能會(huì)產(chǎn)生一些運(yùn)行期間重復(fù)的公共文件,造成代碼體積大冗余,同時(shí)也會(huì)減慢編譯效率。 可以加上cacheDirectory參數(shù)或使用 transform-runtime 插件試試。

// webpack.config.js
  use: [{
      loader: 'babel-loader',
      options: {
          cacheDirectory: true
  }]
  // .bablerc
  {
      "presets": [
          "env",
          "react"
      ],
      "plugins": ["transform-runtime"]
  }

7. 不需要打包編譯的插件庫(kù)換成全局"script"標(biāo)簽引入的方式

比如jQuery插件,react, react-dom等,代碼量是很多的,打包起來(lái)可能會(huì)很耗時(shí) 可以直接用標(biāo)簽引入,然后在webpack配置里使用 expose-loader 或 externals 或 ProvidePlugin 提供給模塊內(nèi)部使用相應(yīng)的變量。

 // @1
  use: [{
      loader: 'expose-loader',
      options: '/pre>
  }, {
      loader: 'expose-loader',
      options: 'jQuery'
  }]
  // @2
  externals: {
      jquery: 'jQuery'
  },
  // @3
  new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
  })

8. 優(yōu)化構(gòu)建時(shí)的搜索路徑

在webpack打包時(shí),會(huì)有各種各樣的路徑要去查詢(xún)搜索,我們可以加上一些配置,讓它搜索地更快 比如說(shuō),方便改成絕對(duì)路徑的模塊路徑就改一下,以純模塊名來(lái)引入的可以加上一些目錄路徑 還可以善于用下resolve alias別名 這個(gè)字段來(lái)配置。 還有exclude等的配置,避免多余查找的文件,比如使用babel別忘了剔除不需要遍歷的。

參考鏈接
webpack面試題匯總
Webpack打包構(gòu)建太慢了?試試幾個(gè)方法
關(guān)于webpack的面試題總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容