webpack概述

若是2020年做爲一個前端開發你還不知道 Webpack 是什麼,真的就要考慮回爐重造了。不少人可能會得意洋洋,嘴角上揚回答:這誰不知道,不就是一個項目構建工具嗎,咱們的項目如今都用着了。這我固然信,可是若是讓你認真介紹 Webpack 核心的概念有哪些,底層的原理是怎麼樣的,那麼你還能淡定地娓娓道來嗎?以前的我可能也跟大部分人同樣,只停留在簡單會用,知道的水平,並且幾乎每一個經歷過的項目也都在使用,也知道 create-react-appvue-cli 底層都是依賴 webpack,可是我以爲做爲一個想要更進階的前端工程師,你須要掌握的更多。這也是爲何我想寫這篇文章的緣由之一,這是也是我從新學習 Webpack 系列的第一篇:Webpack概述。javascript

一句話介紹

先看官網的介紹:css

webpack is a static module bundler for modern JavaScript applications.html

翻譯過來大概的意思就是 Webpack 是一個現代的 JavaScript 應用 模塊 打包器。首先咱們要清楚它的定位是爲 JavaScript 應用 服務的,有時候咱們開發一些組件庫、工具庫,開發完後也須要有一個打包構建、上線這樣一個過程,這種類型的項目咱們通常不用 Webpack,而是用 Rollup 這樣的工具。第二,咱們要注意的是,上面我特地加粗的另外一個關鍵詞:模塊。那麼在 Webpack 眼裏到底哪些是模塊?前端

一切皆模塊

隨着 Commonjs 的出現,CMDAMD 模塊思想的誕生,ES Module 逐漸成爲標準, JavaScript 終於進入了模塊化編程的時代。模塊化編程使得咱們更好的組織JS代碼,合理的劃分也使得代碼更容易調試、測試。NodeJS誕生的時候就有本身的模塊化,而Web的模塊進展一直比較緩慢。與Node.js模塊相比,webpack模塊能夠用多種方式表達模塊之間的依賴關係。下面是一些例子:vue

  • ES2015 import
  • CommonJS require()
  • AMD的 definerequire
  • css/sass/less 文件中的 @import
  • 樣式文件中的圖片 url(...) 和 HTML 中的<img src="...">

Webpack 也支持各類各樣的模塊,下面是一些經常使用的例子:java

  • TypeScript
  • ESNext
  • Sass
  • Less
  • Stylus
  • Vue
  • ...

咱們知道 Webpack 主要是一個 JavaScript 的打包器,那麼它怎麼識別和處理其它的非JS模塊呢?這就牽涉到 Webpack 最重要的概念: Loader,下面咱們開始介紹 Webpack 的核心概念。react

核心概念


Entry

入口代表了 Webpack 從哪一個模塊開始構建內部的依賴圖,Webpack 將找出入口所依賴的其它模塊和庫。它的默認值是 src/index.js,你也能夠經過配置指定不一樣的路徑:webpack

module.exports = {
  entry: './path/to/my/entry/file.js'
};
複製代碼

你也能夠配置多個入口,在開發多頁面應用的時候就可能須要配置多個入口:web

module.exports = {
  entry: {
    app: './src/app.js',
    adminApp: './src/adminApp.js'
  }
};
複製代碼

Output

既然有入口,那就有出口,出口選項告訴 Webpack 構建好的 bundles 放在哪一個目錄下以及怎麼命名輸出的文件。默認值是:./dist/main.js,輸出的文件默認都放在 dist 目錄下。固然你也能夠自定義本身的 output 選項:正則表達式

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};
複製代碼

在上面的例子中,output.path 告訴 Webpack 輸出的文件放在什麼目錄下,output.filename 指明生成的文件命名規則。

Loaders

前面咱們提到了一切資源(字體文件、圖片、CSS、預編譯器Sass等)甚至 Vue 組件在 Webpack 中都被當成模塊來處理,可是 Webpack 自身其實只是一個 JavaScript Bundler ,它只認識JS模塊和JSON文件。因爲在一個複雜的Web應用中,咱們不僅有JS模塊,也有HTML、CSS、圖片等資源,若是使用框架,還須要 Vue SFCReact jsx等,因此這時候就須要 Loaders 出馬了。Loaders 可使得 Webpack 可以處理各類類型的模塊,處理完後再把它們加入到依賴圖中。

每一個 loader 配置主要有兩個選項:

  • test 選項,確認哪些些文件將被 loader 轉換,通常是一個正則表達式;
  • use 選項,代表哪些 loaders 將被用來轉換文件。

下面看一個例子:

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' }
    ]
  }
};
複製代碼

上面的例子,定義了一個 loader 轉換規則,它告訴 Webpack 編譯器,當發現js 文件的時候,使用 babel-loader 進行轉換。

咱們還能夠配置多個 loader,好比下面這個例子:

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          // style-loader
          { loader: 'style-loader' },
          // css-loader
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          },
          // sass-loader
          { loader: 'sass-loader' }
        ]
      }
    ]
  }
};
複製代碼

上面這個例子告訴 Webpack 編譯器,當遇到以 .scss 結尾的文件,先用 sass-loader 處理,接着再用 css-loader 轉化,最後使用 style-loader 完成此類文件的處理,它的處理順序是從後往前。

Plugins

Loaders 幫助 Webpack 處理不一樣類型的文件和模塊,而插件被用來擴展 Webpack 的功能,使得Webpack 更增強大,插件能夠用來優化 bundle(壓縮文件、tree shaking、code split等)、管理靜態資源和注入環境變量。

使用一個插件以前,首先經過 require 引入插件,而後將它添加到 plugins 選項數組中,大部分插件支持一些選項配置。因爲能夠在配置中爲不一樣的需求屢次使用插件,因此你須要經過使用new操做符調用插件來建立它的實例:

const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './public/index.html'})
  ]
};
複製代碼

在上面的例子中,html-webpack-plugin 將會爲你的應用生成一個 html 文件,而且這個文件會被自動注入 Webpack 處理生成的全部 bundle

Webpack 中配置插件仍是比較簡單的,關鍵是你要了解生態中有哪些優秀的插件能夠直接拿來使用,挑選出適合你本身項目的插件組合,在沒有合適的插件支撐你的業務需求時,你也選擇能夠開發本身的 Webpack 插件。

以上是我以爲在 Webapck 中比較核心的概念,這些是你學習 Webpack 必須掌握的概念,EntryOutput 可能相對簡單,LoadersPlugins 機制是核心中的核心,其底層的原理也值得仔細探究,後續的文章中我會對其進行分析。

補充

在官方文檔中,還提到兩個點能夠注意一下。一個是 mode,經過設置不一樣的值,告訴 Webpack 當前是開發環境仍是生產環境。其主要的值有 developmentproductionnone,對於每一個選項, Wepack 都會在底層作相應環境的一些優化,它的默認值是:production

第二個點是 Browser Compatibility,也就是瀏覽器兼容性。webpack支持全部兼容es5的瀏覽器(不支持IE8及如下版本)。Webpack 中的 import()require.ensure() 須要支持Promise,若是你想支持較老的瀏覽器,須要 引入 Polyfill ,想要了解更多,能夠查看:load polyfill

相關文章
相關標籤/搜索