webpack4學習筆記

這裏有一份簡潔的前端知識體系等待你查收,看看吧,會有驚喜哦~若是以爲不錯,麻煩star哈~css


前言

webpack 是當下最好用的前端模塊打包工具,前端開發人員平常都要跟腳手架打交道,而手腳架就是基於webpack構建的,深刻理解webpack,對咱們平常工做意義重大。html

本文將系統講解webpack,老規矩,從應用維度跟設計維度展開,因爲做者能力有限,有些部分暫時整理不出來,若是你有所補充,歡迎push~前端


應用維度


問題

從技術的應用維度看,首先考慮的是要解決什麼問題,這是技術產生的緣由。問題這層,用來回答「幹什麼用」。node


隨着前端的演變,網頁已經至關於一個功能豐富的應用,前端面臨諸多挑戰:react

  1. 首先,前端代碼愈來愈複雜,就須要模塊化開發,模塊化開發帶來的問題就是代碼如何組織,如何處理依賴關係?
  2. 前端社區日益繁榮,平常開發已經離不開第三方依賴,如何管理好第三方依賴,也成爲一個問題。
  3. 瀏覽器對ES6的兼容還不夠友好,這也是前端須要解決的問題
  4. 上線時咱們須要對代碼進行打包,這樣能夠有效減小http請求,從而提升性能
  5. 咱們要打包的文件,不只包含JS,還可能包含CSS、image等。

因爲前端界存在種種問題,webpack應運而生。jquery

webpack官方定義就是一個模塊打包工具。webpack不只支持 ES module 的語法,也支持 CommonJS 的語法。webpack

webpack 不只能夠打包JS,也能夠打包其餘格式的文件, 好比css、image等。git


技術規範

技術被研發出來,人們怎麼用它才能解決問題呢?這就要看技術規範,能夠理解爲技術使用說明書。技術規範,回答「怎麼用」的問題,反映你對該技術使用方法的理解深度。github


這裏要重點講解webpack的配置。web

模式

webpack 配置文件須要指定 mode,默認是production,打包後的文件會被壓縮。能夠指定成 development。不設置mode,會有警告

module.exports = {
  // ……
  mode: 'production',
}
複製代碼

Entry 與 Output

entry 支持配置多項,每一項的key是文件名,當entry配置多個入口文件時,output的filename不能寫死,否則會報錯,能夠寫成 filename: [name].js

output 還能夠配置publicPath,從而設置導出JS文件的前綴,經過這個配置,能夠設置CDN地址。

module.exports = {
  entry: {
    main: './src/index.js',
    sub: './src/index.js'
  },
  output: {
    filename: '[name].js', // 設置成 index.js 會報錯
    chunkFilename: '[name].chunk.js',
    publicPath: 'http://cdn.com',
    path: path.resolve(__dirname, '../dist')
  }
}
複製代碼

Loader

loader就是打包方案。

好比,打包jpg圖片時,可使用 file-loader 進行打包,也可使用url-loader,url-loader包含了 file-loader 全部的功能,並且,他默認會將圖片轉成base64格式。若是不但願轉成base64位,能夠設置 limit,這樣的話,當圖片大於設置值的時候,就不會轉成base64。

// webpack.config.js
module.exports = {
  module: {
    rules: [{
      test: /\.(jpg|png|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name]_[hash].[ext]',
          outputPath: 'images/',
          limit: 10240
        }
      }
    }]
  }
}
複製代碼

又好比,打包css文件時,須要同時引入兩個loader:css-loader跟style-loader。css-loader會分析css文件的引用關係,最後把css文件合併成一段css。而style-loader的做用是把這段css放到head下的style標籤下。

若是是scss文件,還須要引入 scss-loader。若是須要css自動添加瀏覽器產商前綴,則須要引入postcss-loader。

因爲css中還能夠引用其餘的css,爲了不出錯,須要在css-loader 中設置importLoaders。

爲了防止css全局污染,咱們須要引入css modules的概念,也就是css模塊化。一樣須要在css-loader 中設置 modules 爲true。引入時可使用相似的方式: import style from './index.css'

若是css中引用了字體文件,還須要對 字體文件的格式設置loader,使用 file-loader 便可。

module.exports = {
  module: {
    rules: [{
      test: /\.scss$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 2
          }
        },
        'sass-loader',
        'postcss-loader'
      ]
    }, {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            modules: true
          }
        },
        'postcss-loader'
      ]
    }, {
      test: /\.(eot|ttf|svg)$/,
      use: {
        loader: 'file-loader'
      }
    }]
  },
}
複製代碼
// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
複製代碼

若是有多個loader時,會從後往前執行。


plugins

使用plugins讓打包更便捷。

plugin 很像生命週期函數,能夠在webpack 運行到某一個時刻,幫你處理一些事情。

htmlWebpackPlugin 會在打包結束後,自動生成一個HTML文件,並把打包生成的JS自動引入到HTML中。

cleanWebpackPlugin 會在打包以前,刪除某一個文件夾(好比dist文件夾)

module.exports = {
  // ……
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }),
    new CleanWebpackPlugin(['dist'], {
      root: path.resolve(__dirname, '../')
    })
  ]
}
複製代碼

sourceMap

sourceMap 是一個映射關係,當咱們打包的文件報錯時,它能提示咱們是源文件的出錯位置,而不是打包後文件的出錯位置,這樣就利於調試。

使用方式,就是在 webpack 中配置 devtool: 'source-map'

development 環境,推薦使用 devtool: 'cheap-module-eval-source-map' production 環境,推薦使用 devtool: 'cheap-module-source-map'

module.exports = {
  // ……
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',
}
複製代碼

webpackDevServer

每次修改代碼都要從新打包,這是很是繁瑣的,咱們能夠修改npm scripts成webpack --watch

但若是咱們想實現更酷炫的效果,好比自動打開瀏覽器、自動刷新瀏覽器等,這個操做就作不到。此時,能夠藉助webpackDevServer 來實現。

webpack支持 devServer , 能夠幫咱們啓動了一個服務器。咱們在平常開發中,常常須要發ajax請求,這大大提升了咱們的開發效率。此外,devServer打包後的文件,其實保存在內存中,這樣打包的速度更快。

以前 devServer 還不夠完善,因此不少腳手架工具會本身實現一個devServer,如今webpack的devServer已經很是完善了。

更多請參考官網

module.exports = {
  devServer: {
    contentBase: './dist', // 服務器的根目錄
    open: true, // 自動打開瀏覽器
    port: 8080,
    hot: true,
    proxy: { // 設置代理,訪問/api,直接轉發到3000端口
      "/api": "http://localhost:3000"
    }
  },
}
複製代碼

咱們也能夠手寫一個 devServer,新建server.js,增長 npm scripts : node server.js

const express = require('express);
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./webpack.config.js');
const complier = webpack(config)

const app = express(); // 啓動一個http服務器
app.use(webpackDevMiddleware(complier, {}))

app.listen(3000, ()=>{
  console.log("server is running");  
})
複製代碼

經過這個例子,也能夠看到webpack有兩種使用方式,一種是在命令行中使用,一種是在node中直接使用webpack。

在命令行使用webpack,能夠參考官網資料

在node中使用webpack,能夠參考官網資料


hot mudule replacement 熱更新

咱們每一次修改代碼,devServer都會幫咱們刷新頁面,但咱們只但願顯示修改的內容,而不刷新頁面,此時就要用到熱更新。

更多請參考官網資料1資料2

const webpack = require('webpack');

module.exports = {
  devServer: {
    contentBase: './dist',
    open: true,
    port: 8080,
    hot: true,
    hotOnly: true, // 可選,即使hot功能不生效,瀏覽器也不刷新
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
}
複製代碼

Babel

有些瀏覽器還不支持ES6的語法,此時就須要用babel轉義,將ES6語法轉成ES5。

babel提供了詳細的使用指南,在官網setup頁面選擇webpack選項就能夠看到。


babel的使用分爲三步:

  1. Installation
npm install --save-dev babel-loader @babel/core
複製代碼

babel-loader @babel/core 是 babel 跟 webpack 之間的橋樑

  1. Usage
module: {
  rules: [
    { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
  ]
}
複製代碼
  1. Create .babelrc configuration file 新建 .babelrc 並按照 env preset
npm install @babel/preset-env --save-dev
複製代碼
// .babelrc
{
  "presets": ["@babel/preset-env"]
}
複製代碼

@babel/preset-env 將ES6的語法轉義成ES5語法,好比let轉成var

@babel/polyfill 爲低級瀏覽器注入了ES6的對象或方法,好比promise

引入 @babel/polyfill 會讓咱們的文件變得很是大,能夠配置 useBuiltIns 作到按需加載

babel 內容很是多,建議直接看官網。


module.exports = {
  // ……
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      options: {
        presets: [["@babel/preset-env", {
          targets: {
            chrome: '67',  // 告訴 babel 目標瀏覽器,babel能夠根據目標瀏覽器決定是否作轉化,這樣就能夠減小最終輸出文件的大小
          },
          useBuiltIns: 'usage  // 提升性能:用到的才引用
        }]]
      }
      // use: [{
      //   loader: 'babel-loader'
      // }, {
      //   loader: 'imports-loader?this=>window'
      // }]
    }]
  },
}
複製代碼

babel-loader 中 options 的內容會很是多,能夠把 options 的內容放到 .babelrc 中


tree shaking

咱們引入一個模塊,只會引入該模塊中的部分方法,tree shaking會幫咱們把不須要的方法過濾掉,這樣打包後的文件將顯著變小。

tree shaking 只支持 ES Module 的引用方式。

development 模式下,默認是不支持 tree shaking,咱們須要配置 optimization 的 usedExports 爲true。

咱們還須要給 package.json 增長一項配置 "sideEffects": ["@babel/polyfill", "*.css"],這樣打包時 tree shaking 對 @babel/polyfill就不會有做用。這是由於咱們引用@babel/polyfill時,是import @babel/polyfill,tree shaking 會認爲 @babel/polyfill 不須要引用任何東西,從而把它忽略掉。同理,咱們可使用 import "index.css",咱們一樣不但願tree shaking生效,咱們能夠在sideEffects中增長 *.css 的配置。

若是設置"sideEffects": false,表示對全部模塊都作 tree shaking。

development 模式下,爲了調試方便,雖然設置了 tree shaking,但打包出來的文件同樣包含沒有引用的模塊。當咱們上線時,會設置 mode 爲 production,此時 tree shaking 就會把不須要模塊的代碼過濾掉。

module.exports = {
  // ……
  mode: 'development',
  optimization: {
    usedExports: true,
  },
}
複製代碼

development 和 production 模式的區分打包

因爲 development 和 production 模式下的配置是不同的,咱們能夠抽離出公共的 webpack.common.js,以及Dev下的 webpack.dev.js 和 production下的webpack.prod.js。最後使用 webpack.merge 合併。

const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');

const devConfig = {
  // ……
}

module.exports = merge(commonConfig, devConfig);
複製代碼

splitChunksPlugin

webpack代碼分割底層使用了 splitChunksPlugin 插件。官網資料地址

module.exports = {
  splitChunks: {
    chunks: "async", // 可選:all。async 只代碼分割異步代碼,all同時支持同步跟異步的方式
    minSize: 30000, // 小於 30KB 不作代碼分割,大於 30KB,還要根據cacheGroups的規則決定是否作代碼分割
    maxSize: 20000, // 大於 20KB 嘗試作代碼分割,但因爲基礎庫是不容許分割的,因此通常不生效
    minChunks: 1,  // 引用超過1次,會作代碼分割。
    maxAsyncRequests: 5, // 遇到的前5個庫,會作代碼分割,超過5個的不作代碼分割
    maxInitialRequests: 3, // 入口文件最多隻能作三次代碼分割
    automaticNameDelimiter: '~', // 文件鏈接符
    name: true, // 爲true時,cacheGroups的filename纔會生效
    cacheGroups: { // 緩存組,知足以上要求的文件,會根據緩存組中的要求,加入緩存組,最終打包成文件。這樣的好處是能夠把多個庫,輸出成一個文件。此外,若是配置了上面的參數卻沒有代碼分割,極可能就是緩存組的配置不知足
      vendors: {
        test: /[\\/]node_modules[\\/]/, // node_modules目錄下的文件會被匹配
        priority: -10, // 優先級,值越大優先級越大
        // filename: 'vendors.js'
      },
      default: {
        minChunks: 2,
        priority: -20,
        reuseExistingChunk: true  // 若是一個模塊已經被打包了,則再打包時會忽略該模塊
      }
    }
  },
}
複製代碼

小技巧:splitChunks 若是不配置,默認值就是上面的這些選項。簡便寫法是:

module.exports = {
  // …… 
  splitChunks: {
    chunks: "all", // 咱們要對同步跟異步代碼都作代碼分割,因此改爲all
  },
}
複製代碼

咱們也能夠爲css進行代碼分割,使用到的插件是MiniCssExtractPlugin,只須要用MiniCssExtractPlugin提供的loader 代替 style-loader 便可,具體內容看官網。


最佳實踐

最佳實踐回答「怎麼能用好」的問題,反映你實踐經驗的豐富程度。


webpack的安裝

webpack 不建議全局安裝,由於每一個項目依賴的webpack版本可能不一樣,全局安裝可能致使項目依賴的webpack版本不對而沒法運行,建議局部安裝,也就是 npm i webpack webpack-cli -D

局部安裝完webpack後,若是要查看webpack的版本,執行 webpack -v是得不到預期的結果,由於webpack並沒全局安裝,此時要執行 npx webpack -v,npx是npm提供的命令,它會在咱們當前目錄下的node_modules文件下尋找安裝過的依賴。

若是咱們是在package.json文件中配置 npm scripts,則不須要npx這個指令,由於 npm scripts 默認會在當前目錄下的 node_modules 尋找依賴。

安裝webpack時,能夠指定webpack的版本號,若是不清楚webpack有什麼版本,可使用npm info webpack查看

webpack-cli 容許咱們在命令裏使用webpack這個命令。

webpack與 code splitting

若是把全部的代碼都打包到一個文件裏,會帶來兩個問題:

  1. 文件過於龐大
  2. 基礎庫基本上不會改變,而業務代碼卻常常改變,一旦業務代碼更改了,整個文件要從新加載,會極大的損耗性能。

code splitting 是代碼分割,沒有webpack咱們也能夠手動作代碼分割,從而提高性能。webpack能幫咱們自動完成代碼分割。

webpack 中實現代碼分割有兩種方式:

  1. 同步代碼,咱們能夠在 optimization 中設置splitChunks。
  2. 異步代碼(import),無需任何配置,會自動進行代碼分割。
module.exports = {
  // ……
  optimization: {
    splitChunks: {
      chunks: 'all',
    }
  },
}
複製代碼

打包分析

咱們可使用webpack提供的analyse工具進行打包分析.

咱們在打包時,須要增長命令webpack --profile --json > stats.json,也就是 webpack --profile --json > stats.json --config ./build/webpack.dev.js

打包完的文件中,就會出現stats.json的文件。

咱們打開連接,上次stats.json,就會出現打包的分析報告。

webpack官方提供的分析工具,除了analyse,還有這些

  1. webpack-chart: webpack 數據交互餅圖。
  2. webpack-visualizer: 可視化並分析你的 bundle,檢查哪些模塊佔用空間,哪些多是重複使用的。
  3. webpack-bundle-analyzer: 一款分析 bundle 內容的插件及 CLI 工具,以便捷的、交互式、可縮放的樹狀圖形式展示給用戶。

Prefetching/Preloading

webpack 建議咱們寫異步加載代碼,也就是異步import。當代碼執行時,纔會去加載相應的代碼,這樣首屏的代碼利用率就能夠提升。相似:

document.addEventListener('click', () => {
  import('./click.js').then(({ default: func }) => {
    func()
  })
})
複製代碼

咱們能夠用Chrome的coverage工具看代碼的利用率。



但咱們不必定要等到用戶操做時,纔去加載相應的代碼,而是在網絡空閒時就去加載。咱們能夠在webpack中進行配置。具體作法以下:

// 關注下魔法註釋,js的新特性
document.addEventListener('click', () => {
  import(/* webpackPrefetch: true */ './click.js').then(({ default: func }) => {
    func()
  })
})
複製代碼

Prefetching/Preloading 是有區別的:

  1. Prefetching會等待覈心代碼加載完,網絡空閒時纔去加載
  2. Preloading是跟主要的代碼一塊加載的

因此Prefetching會更合適。


webpack 與 瀏覽器緩存

咱們打包的文件,瀏覽器是會緩存的,當咱們修改了內容,用戶刷新頁面,此時加載的仍是緩存中的文件。爲了解決這個問題,咱們須要修改production模式下的配置文件。

const commonConfig = require('./webpack.common.js');

const prodConfig = {
  mode: 'production',
  devtool: 'cheap-module-source-map',
  output: {
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js'
  },
  optimization: {
    runtimeChunk: {
      name: 'runtime'  // 舊版本必須配置此項,不然即使文件內容沒有發生改變,hash值也會改變
    },
  }
}

module.exports = merge(commonConfig, prodConfig);
複製代碼

contenthash 會根據文件內容生成hash值,當咱們文件內容改變時,contenthash就會改變,從而通知瀏覽器從新向服務器請求文件。

之因此在舊版webpack下,文件代碼沒變,生成文件的hash值也會改變的緣由是:

咱們業務邏輯的代碼打包到main.js裏,依賴庫的代碼打包到vendors.js裏,但main.js跟vendors.js是有依賴關係的,這些依賴關係的代碼會保存在manifest文件裏。manifest文件既存在於main.js,也存在vendors.js裏。而在舊版webpack每次打包manifest可能會有差別,這個差別致使vendors.js的hash值也會改變。設置runtimeChunk後,manifest相關的代碼會被抽離出來,放到runtime文件裏去,這樣就能解決這個問題。


Shimming 墊片

jQuery時代,咱們須要先引入jQuery,再引入其餘依賴jQuery的類庫,好比jQuery.ui.js。這在webpack中就有問題。好比這樣:

// a.js
import $ from 'jquery'
import 'jquery.ui'
複製代碼

這樣引用,jquery.ui.js會報錯:找不到。之因此這樣,是由於webpack是模塊化,只能在a.js裏引用,jquery.ui.js是引用不到$的,而jquery.ui.js是第三方庫,咱們又不能去修改jquery.ui.js的代碼,怎麼辦呢?

咱們能夠添加ProvidePlugin插件。在ProvidePlugin裏咱們設置了,當JS文件中用到,在當前又沒引用時,這個配置就會生效,告訴JS文件指向jquery。

關於ProvidePlugin,能夠到官網看資料

const webpack = require('webpack');
module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      _join: ['lodash', 'join']
    }),
  ],
  performance: false, // 額外補充:設置爲false,打包時不會警告性能方面的問題
}
複製代碼

關於墊片機制,還有其餘用法。好比咱們在一個模塊中全局打印this,發現this指向的是模塊自己,而不是window對象,若是想要讓this指向window,能夠這樣:

module.exports = {
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      use: [{
        loader: 'babel-loader'
      }, {
        loader: 'imports-loader?this=>window'
      }]
    }]
  },
}
複製代碼

咱們須要安裝imports-loader,設置this指向window。

關於shimming,能夠看官網資料


library 的打包

咱們寫的庫,要支持多種方式的引用,諸如:

// library.js
export function math (){
  console.log(1);
}
複製代碼
import library from './library' // ES module
const library = require('library'); // commonjs
require(['library'], function(){}) // AMD
複製代碼

咱們能夠配置libraryTarget:

module.exports = {
  mode: 'production',
  entry: {
    main: './src/index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    libraryTarget: 'umd' // umd 是通用的意思。配置了umd,就能夠支持不一樣的引用方式
  }
}
複製代碼

若是你還想經過script標籤引用,好比<script src="./library.js"></script>,那還須要配置

module.exports = {
  mode: 'production',
  entry: {
    main: './src/index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    library: 'library', // 打包好的代碼,掛載到頁面library這個全局變量上
    libraryTarget: 'umd' // umd 是通用的意思。配置了umd,就能夠支持不一樣的引用方式
  }
}
複製代碼

打包後到瀏覽器控制檯輸入library,就會打印出全局變量



這裏要重點講下 library 跟 libraryTarget 的關係。library的含義是要生成一個全局變量, libraryTarget 的含義是這個全局變量掛載到哪裏。若是libraryTarget設置爲umd,則二者關係不大。若是咱們把libraryTarget 設置成this,則打包出來的文件不支持ES module、commonjs等的引用,他表示全局變量掛載到全局的this上。此時咱們在瀏覽器控制檯,輸入this.library,就能夠找到該全局變量。libraryTarget 還設置成 window、global。

此外,咱們在打包時,還會出現一種狀況:

// library.js
import _ from lodash;
// 其餘代碼
複製代碼
// a.js
import _ from lodash;
import library from './library';
複製代碼

這就形成lodash被打包了兩次,咱們但願library.js打包時,不要把lodash打包進去,能夠這樣配置:

module.exports = {
  externals: ['lodash] // 打包時,遇到lodash,自動忽略
}
複製代碼

PWA

咱們把生成的文件放到線上,用戶就能夠訪問,若是服務器掛了,頁面就會顯示異常。這種時候,咱們但願即使服務器掛了,用戶仍是能夠看到以前訪問的頁面,而這就是PWA。

要作到PWA很簡單,首先配置webpack。

const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
module.exports = {
  plugins: [
    new WorkboxWebpackPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    }),
  ]
}
複製代碼

而後在業務代碼中,使用 serviceWorker。

if('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('service-worker register')
      }).catch(error => {
        console.log('service-worker register error')
      })
  })
}
複製代碼

請求轉發

咱們在開發時,常常會遇到跨域的問題,devServer 能夠幫助咱們實現請求轉發,具體看官網資料

咱們只須要在webpack進行以下配置:

module.exports = {
  devServer: {
    proxy: {
      '/react/api': {
        target: 'https://baidu.com/',
        secure: false, // false 時才能夠對https請求的轉發
        pathRewrite: {
          'header.json': 'demo.json'
        }
      }
    }
  },
}
複製代碼

devServer 中的proxy容許咱們作請求轉發。當咱們請求'/react/api'就會被轉發到http://baidu.com/的域名下。此外,咱們在平常開發中,可能須要用到header.json這個API時,該API還沒開發完,咱們須要先訪問demo.json進行開發,此時就能夠設置pathRewrite達到效果。

webpack的proxy內容很是多,底層使用的是http-proxy-middleware,能夠上GitHub看相應的資料


單頁面路由問題

咱們在寫react應用時,須要用到react-router-dom實現路由,可是咱們會發現,當咱們訪問/list時,預期是要訪問到/list路由,但瀏覽器會發送請求到/list,從而頁面顯示出錯。

要解決這個問題,就要用到devServer的historyApiFallback這個API了。

當咱們在devServer裏配置historyApiFallback:true後,咱們無論訪問什麼url,都會執行根目錄(也就是/)下的代碼,從而解決了單頁路由的問題。

更多內容,看官網


eslint

eslint 跟 webpack關係不大,不少編輯器是能夠支持eslint插件,但可能咱們爲了調試方便,但願eslint的錯誤顯示在瀏覽器上,這樣即使咱們編輯器沒有eslint插件,也能夠看到問題。

操做起來也很簡單,咱們先在本身的工程裏安裝eslint跟eslint-loader.

module.exports = {
  devServer: {
    overlay: true  // 必須配置
  },
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: ["babel-loader", "eslint-loader"],  // 使用 eslint-loader 
    },
  ]
}
複製代碼

關於eslint-loader,能夠看官網資料


webpack性能優化

  1. 跟上技術迭代(Node yarn npm )
  2. 在儘量少的模塊上應用loader
  3. plugin 儘量精簡併確保可靠
  4. 合理配置resolve。
  5. 使用 DllPlugin 提升打包速度(5.十、5.11)
  6. 控制包文件大小
  7. 合理使用sourceMap
  8. 結合 stats 分析打包結果
  9. 開發環境內存編譯(devServer打包文件存於內存,能提升速度)

跟上技術迭代

webpack運行於node,node版本更新,天然會提升webpack的打包效率,npm跟yarn等包管理工具也是同理。


在儘量少的模塊上應用loader

爲loader配置exclude,例如: exclude: /node_moudles/ 爲loader配置include,例如:include: path.resolve(__dirname, '../src')


plugin 儘量精簡併確保可靠

好比開發環境下,不須要對代碼進行壓縮,這樣就不須要在webpack.dev.js裏引入相關的plugin


合理配置resolve

當咱們沒有寫js後綴時,webpack默認會幫咱們補上,若是咱們的jsx文件也不但願寫上後綴,但願webpack會幫咱們默認補上,能夠設置resolve。


module.exports = {
  resolve: {
    extensions: ['.js', '.jsx'],
    mainFiles: ['index', 'child'] // 當咱們引用的是某個路徑,webpack默認會幫咱們讀取index文件,若是咱們設置了['index', 'child'],webpack會逐一幫咱們查找index.js index.jsx child.js child.jsx
  }
}
複製代碼

市場應用趨勢

隨着技術生態的發展,和應用問題的變遷,技術的應用場景和流行趨勢會受到影響。這層回答「誰用,用在哪」的問題,反映你對技術應用領域的認識寬度。


設計維度


目標

爲了解決用戶的問題,技術自己要達成什麼目標。這層定義「作到什麼」。


webpack就是個模塊打包工具,咱們須要使用webpack打包不限於JS、CSS、image等文件。

不一樣的文件,打包策略是不一樣的,因此咱們須要配置loader。

打包過程當中,咱們可能還須要作一些額外的操做,因此咱們須要配置 plugin。

因此學習webpack的重點,就是理解與掌握loader跟plugin。

webpack 默認會讀取 webpack.config.js文件,咱們也能夠更改默認的文件名npx webpack --config webpack.xxx.js

注:webpack開發團隊爲了提升開發體驗,一直在豐富webpack的默認配置,因此咱們雖然沒有指定JS的打包策略,但同樣能夠打包成功。


實現原理

爲了達到設計目標,該技術採用了什麼原理和機制。實現原理層回答「怎麼作到」的問題。把實現原理弄懂,而且講清楚,是技術人員的基本功。


優劣侷限

每種技術實現,都有其侷限性,在某些條件下能最大化的發揮效能,缺乏了某些條件則暴露出其缺陷。優劣侷限層回答「作得怎麼樣」的問題。對技術優劣侷限的把握,更有利於應用時總結最佳實踐,是分析各類「坑」的基礎。

演進趨勢

技術是在迭代改進和不斷淘汰的。瞭解技術的前生後世,分清技術不變的本質,和變化的脈絡,以及與其餘技術的共生關係,能體現你對技術發展趨勢的關注和思考。這層體現「將來如何」。

相關文章
相關標籤/搜索