webpack4.0 入門篇 - 構建前端開發的基本環境

什麼是 webpack

webpack 能夠看作是模塊打包機:他作的事情是,分析你的項目結構,找到 JavaScript 模塊以及其餘的一些瀏覽器不能直接運行的擴展語言(ScssTypeScript 等),將其打包爲合適的格式以供瀏覽器使用css

構建就是把源代碼轉換成發佈到線上可執行的 JavaScript、CSS、HTML 代碼,包括如下內容:html

  • 代碼轉換TypeScript 編譯成 JavaScriptSCSS 編譯成 CSS 等等
  • 文件優化:壓縮 JavaScript、CSS、HTML 代碼,壓縮合並圖片等
  • 代碼分割:提取多個頁面的公共代碼、提取首屏不須要執行部分的代碼讓其異步加載
  • 模塊合併:在採用模塊化的項目有不少模塊和文件,須要構建功能把模塊分類合併成一個文件
  • 自動刷新:監聽本地源代碼的變化,自動構建,刷新瀏覽器
  • 代碼校驗:在代碼被提交到倉庫前須要檢測代碼是否符合規範,以及單元測試是否經過
  • 自動發佈:更新完代碼後,自動構建出線上發佈代碼並傳輸給發佈系統。

構建實際上是工程化、自動化思想在前端開發中的體現。把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。前端

webpack 的基本概念

  • 入口(entry point): 指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始,webpack 會找出有哪些模塊和 library 是入口起點(直接和間接)依賴的。vue

    • 默認值是 ./src/index.js,然而,能夠經過在 webpack 配置中配置 entry 屬性,來指定一個不一樣的入口起點(或者也能夠指定多個入口起點)。
  • 出口 output: 屬性告訴 webpack 在哪裏輸出它所建立的 bundles,以及如何命名這些文件,主輸出文件默認爲 ./dist/main.js,其餘生成文件的默認輸出目錄是 ./distnode

  • loader: 讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後你就能夠利用 webpack 的打包能力,對它們進行處理。react

注意,loader 可以 import 導入任何類型的模塊(例如 .css 文件),這是 webpack 特有的功能,其餘打包程序或任務執行器的可能並不支持。咱們認爲這種語言擴展是有很必要的,由於這可使開發人員建立出更準確的依賴關係圖。webpack

  • 插件 plugins: loader 被用於轉換某些類型的模塊,而插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量。插件接口功能極其強大,能夠用來處理各類各樣的任務。ios

  • 模式 mode: 經過選擇 developmentproduction 之中的一個,來設置 mode 參數,你能夠啓用相應模式下的 webpack 內置的優化git

webpack 構建過程

  1. 從 Entry 裏配置的 Module 開始遞歸解析 Entry 依賴的全部 Module。
  2. 每找到一個 Module, 就會根據配置的 Loader 去找出對應的轉換規則。
  3. 對 Module 進行轉換後,再解析出當前 Module 依賴的 Module。
  4. 這些模塊會以 Entry 爲單位進行分組,一個 Entry 和其全部依賴的 Module 被分到一個組也就是一個 Chunk。
  5. 最後 Webpack 會把全部 Chunk 轉換成文件輸出。
  6. 在整個流程中 Webpack 會在恰當的時機執行 Plugin 裏定義的邏輯。

開發環境和生產環境

咱們在平常的前端開發工做中,通常都會有兩套構建環境:一套開發時使用,一套供線上使用。es6

  • development: 用於開發的配置文件,用於定義 webpack dev server 和其餘東西
  • production: 用於生產的配置文件,用於定義 UglifyJSPluginsourcemaps

簡單來講,開發時可能須要打印 debug 信息,包含 sourcemap 文件,而生產環境是用於線上的即代碼都是壓縮後,運行時不打印 debug 信息等。譬如 axios、antd 等咱們的生產環境中須要使用到那麼咱們應該安裝該依賴在生產環境中,而 webpack-dev-server 則是須要安裝在開發環境中

平時咱們 npm 中安裝的文件中有 -S -D, -D 表示咱們的依賴是安裝在開發環境的,而-S 的是安裝依賴在生產環境中。

本文就來帶你搭建基本的前端開發環境,前端開發環境須要什麼呢?

  • 構建發佈須要的 HTML、CSS、JS、圖片等資源
  • 使用 CSS 預處理器,這裏使用 less
  • 配置 babel 轉碼器 => 使用 es6+
  • 處理和壓縮圖片
  • 配置熱加載,HMR

以上配置就能夠知足前端開發中須要的基本配置。下面是本文打包後的效果圖:

搭建基本的開發環境

安裝

mkdir webpack-dev && cd webpack-dev
npm init -y
npm i webpack webpack-cli -D
複製代碼

添加 scripts

生成了 package.json 文件,在文件中添加

"scripts": {
    "build": "webpack --mode production"
  }
複製代碼

--mode 模式 (必選,否則會有 WARNING),是 webpack4 新增的參數選項,默認是 production

  • --mode production 生產環境
    • 提供 uglifyjs-webpack-plugin 代碼壓縮
    • 不須要定義 new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) 默認 production
    • 默認開啓 NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors, 編譯出錯時跳過輸出,以確保輸出資源不包含錯誤
    • 默認開啓 ModuleConcatenationPlugin -> optimization.concatenateModules, webpack3 添加的做用域提高(Scope Hoisting)
  • --mode development 開發環境
    • 使用 eval 構建 module, 提高增量構建速度
    • 不須要定義 new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }) 默認 development
    • 默認開啓 NamedModulesPlugin -> optimization.namedModules 使用模塊熱替換(HMR)時會顯示模塊的相對路徑

添加了 scripts 以後,新建src/index.js,而後執行npm run build ,你就會發現新增了一個 dist 目錄,裏邊存放的是 webpack 構建好的 main.js 文件。

ps npm scripts 使用指南

新建 webpack.config.js 文件

要想對 webpack 中增長更多的配置信息,咱們須要創建一個 webpack 的配置文件。在根目錄下建立 webpack.config.js 後再執行 webpack 命令,webpack 就會使用這個配置文件的配置了

配置中具有如下的基本信息:

module.exports = {
  entry: '', // 打包入口:指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始
  output: '', // 出口
  resolve: {}, // 配置解析:配置別名、extensions 自動解析肯定的擴展等等
  devServer: {}, // 開發服務器:run dev/start 的配置,如端口、proxy等
  module: {}, // 模塊配置:配置loader(處理非 JavaScript 文件,好比 less、sass、jsx、圖片等等)等
  plugins: [] // 插件的配置:打包優化、資源管理和注入環境變量
}
複製代碼

配置打包入口和出口

首先咱們往 webpack.config.js 添加點配置信息

const path = require('path')

module.exports = {
  // 指定打包入口
  entry: './src/index.js',

  // 打包出口
  output: {
    path: path.resolve(__dirname, 'dist'), // 解析路徑爲 ./dist
    filename: 'bundle.js'
  }
}
複製代碼

上面咱們定義了打包入口 ./src/index.js,打包出口爲 ./dist, 打包的文件夾名字爲bundle.js,執行npm run build命令後,index.js 文件會被打包爲 bundle.js 文件。此時隨便創建一個 html 文件引用這個bundle.js就能夠看到你在index.js 寫的代碼了。

path.resolve([...paths]) 方法會把一個路徑或路徑片斷的序列解析爲一個絕對路徑。

使用 html-webpack-plugin 建立 html 文件

更多狀況下咱們不但願打包一次,就新建一次 html 文件來引用打包後的文件,這樣顯得不智能或者說當你打包的文件名修改後,引用路徑就會出錯。

這個時候咱們就可使用 html-webpack-plugin 插件來將 HTML 引用路徑和咱們的構建結果關聯起來。

npm install html-webpack-plugin -D
複製代碼

建立文件public/index.html 修改 webpack.config.js 文件

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  //...
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置輸出文件名和路徑
      template: './public/index.html' // 配置要被編譯的html文件
    })
  ]
}
複製代碼

從新執行 npm run build, dist 目錄就會多個 index.html 並引入了 bundle.js.

壓縮 html 文件

修改 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  //...
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置輸出文件名和路徑
      template: './public/index.html', // 配置要被編譯的html文件
      hash: true,
      // 壓縮 => production 模式使用
      minify: {
        removeAttributeQuotes: true, //刪除雙引號
        collapseWhitespace: true //摺疊 html 爲一行
      }
    })
  ]
}
複製代碼

打包 css 文件

咱們但願使用 webpack 來進行構建 css 文件,,爲此,須要在配置中引入 loader 來解析和處理 CSS 文件:

npm install style-loader css-loader -D
複製代碼

新建 src/assets/style/color.css, 修改 webpack.config.js 文件:

module.exports = {
  //...
  module: {
    /** * test: 匹配特定條件。通常是提供一個正則表達式或正則表達式的數組 * include: 匹配特定條件。通常是提供一個字符串或者字符串數組 * exclude: 排除特定條件 * and: 必須匹配數組中的全部條件 * or: 匹配數組中任何一個條件, * nor: 必須排除這個條件 */
    rules: [
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, 'src')],
        use: ['style-loader', 'css-loader']
      }
    ]
  }
  //...
}
複製代碼

經由上述兩個 loader 的處理後,CSS 代碼會轉變爲 JS, 若是須要單獨把 CSS 文件分離出來,咱們須要使用 mini-css-extract-plugin 插件

抽取 css 到獨立文件, 自動添加前綴

npm i mini-css-extract-plugin postcss-loader autoprefixer -D
複製代碼

咱們在寫 css 時難免要考慮到瀏覽器兼容問題,如 transform 屬性,須要添加瀏覽器前綴以適配其餘瀏覽器。故使用到 postcss-loader 這個 loader, 下面則是相關的配置

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, 'src')],
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [require('autoprefixer')]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    //...
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    })
  ]
}
複製代碼

打包 less 文件

開發中一般會用到一門預處理語言,這裏以less爲例,經過less-loader能夠打包 less 爲 css 文件

npm install less less-loader -D
複製代碼

新建 src/assets/style/index.less, 而且在 src/index.js 中引入 import './assets/style/index.less'

配置 webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  module: {
    rules: [
      // ...
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [require('autoprefixer')] // 添加css中的瀏覽器前綴
            }
          },
          'less-loader'
        ]
      }
    ]
  }
  //...
}
複製代碼

執打包命令後就能夠發現 index.less 中寫的樣式會和color.css同樣被打包進 main.css中。

webpack@v4 升級踩坑: 關於使用 mini-css-extract-plugin 的注意點。

打包圖片

npm install file-loader url-loader -D
複製代碼

file-loader: 能夠用於處理不少類型的文件,它的主要做用是直接輸出文件,把構建後的文件路徑返回。

url-loader: 若是圖片較多,會發不少 http 請求,會下降頁面性能。url-loader 會將引入的圖片編碼,生成 dataURl。至關於把圖片數據翻譯成一串字符。再把這串字符打包到文件中,最終只須要引入這個文件就能訪問圖片了。固然,若是圖片較大,編碼會消耗性能。所以 url-loader 提供了一個 limit 參數,小於 limit 字節的文件會被轉爲 DataURl,大於 limit 的還會使用 file-loader 進行 copy。

  • url-loader 能夠看做是加強版的 file-loader。
  • url-loader 把圖片編碼成 base64 格式寫進頁面,從而減小服務器請求。
module.exports = {
  module: {
    rules: [
      // ...
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              outputPath: 'images/', //輸出到images文件夾
              limit: 500 //是把小於500B的文件打成Base64的格式,寫入JS
            }
          }
        ]
      }
    ]
  }
  //...
}
複製代碼

url-loader 和 file-loader 是什麼關係呢?

簡單地說,url-loader 封裝了 file-loaderurl-loader 不依賴於 file-loader,即便用 url-loader 時,只須要安裝 url-loader 便可,不須要安裝 file-loader,由於 url-loader 內置了 file-loader

經過上面的介紹,咱們能夠看到,url-loader 工做分兩種狀況:

  • 文件大小小於 limit 參數,url-loader 將會把文件轉爲 DataURL;
  • 文件大小大於 limit,url-loader 會調用 file-loader 進行處理,參數也會直接傳給 file-loader。所以咱們只須要安裝 url-loader 便可。

有關 url-loaderfile-loader 的解析:webpack 之圖片引入-加強的 file-loader:url-loader

配置 babel

babel-loader

Babel 是一個讓咱們可以使用 ES 新特性的 JS 編譯工具,咱們能夠在 webpack 中配置 Babel,以便使用 ES六、ES7 標準來編寫 JS 代碼。

Babel 7 的相關依賴包須要加上 @babel scope。一個主要變化是 presets 設置由原來的 env 換成了 @babel/preset-env, 能夠配置 targets, useBuiltIns 等選項用於編譯出兼容目標環境的代碼。其中 useBuiltIns 若是設爲 "usage",Babel 會根據實際代碼中使用的 ES6/ES7 代碼,以及與你指定的 targets,按需引入對應的 polyfill,而無需在代碼中直接引入 import '@babel/polyfill',避免輸出的包過大,同時又能夠放心使用各類新語法特性。

npm i babel-loader @babel/core @babel/preset-env -D
複製代碼

筆者這裏配的版本號以下

{
  "babel-loader": "^8.0.4",
  "@babel/core": "^7.1.2",
  "@babel/preset-env": "^7.1.0"
}
複製代碼
  • babel-loader: 用 babel 轉換 ES6 代碼須要使用到 babel-loader
  • @babel-preset-env: 默認狀況下是等於 ES2015 + ES2016 + ES2017,也就是說它對這三個版本的 ES 語法進行轉化。
  • @babel/core:babel 核心庫

根目錄下新建 .babelrc 文件

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "targets": {
          "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
        },
        "useBuiltIns": "usage"
      }
    ]
  ]
}
複製代碼
  • presets 是一堆 plugins 的預設,起到方便的做用。
  • plugins 是編碼轉化工具,babel 會根據你配置的插件對代碼進行相應的轉化。

修改 webpack.config.js

module.exports = {
  module: {
    rules: [
      //...
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
}
複製代碼

babel/polyfill 和 transform-runtime

Babel 默認只轉換新的 JavaScript 句法(syntax),而不轉換新的 API ,好比 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(好比 Object.assign)都不會轉碼。

  • babel-polyfill: 如上述所說,對於新的 API,你可能須要引入 babel-polyfill 來進行兼容

  • 關鍵點

    • babel-polyfill 是爲了模擬一個完整的 ES2015+環境,旨在用於應用程序而不是庫/工具。
    • babel-polyfill 會污染全局做用域

babel-runtime 的做用:

  • 提取輔助函數。ES6 轉碼時,babel 會須要一些輔助函數,例如 _extend。babel 默認會將這些輔助函數內聯到每個 js 文件裏, babel 提供了 transform-runtime 來將這些輔助函數「搬」到一個單獨的模塊 babel-runtime 中,這樣作能減少項目文件的大小。
  • 提供 polyfill:不會污染全局做用域,可是不支持實例方法如 Array.includes

babel-runtime 更像是分散的 polyfill 模塊,須要在各自的模塊裏單獨引入,藉助 transform-runtime 插件來自動化處理這一切,也就是說你不要在文件開頭 import 相關的 polyfill,你只需使用,transform-runtime 會幫你引入。

對於開發應用來講,直接使用上述的按需 polyfill 方案是比較方便的,但若是是開發工具、庫的話,這種方案未必適合(babel-polyfill 是經過向全局對象和內置對象的 prototype 上添加方法實現的,會形成全局變量污染)。Babel 提供了另一種方案 transform-runtime,它在編譯過程當中只是將須要 polyfill 的代碼引入了一個指向 core-js 中對應模塊的連接(alias)。關於這兩個方案的具體差別和選擇,能夠自行搜索相關教程,這裏再也不展開,下面提供一個 transform-runtime 的參考配置方案。

  • 首先安裝 runtime 相關依賴
npm i @babel/plugin-transform-runtime -D
npm i @babel/runtime -S
複製代碼

修改 .babelrc

{
  //...
  "plugins": ["@babel/plugin-transform-runtime"]
}
複製代碼

打包前清理源目錄文件 clean-webpack-plugin

每次打包,都會生成項目的靜態資源,隨着某些文件的增刪,咱們的 dist 目錄下可能產生一些再也不使用的靜態資源,webpack 並不會自動判斷哪些是須要的資源,爲了避免讓這些舊文件也部署到生產環境上佔用空間,因此在 webpack 打包前最好能清理 dist 目錄。

npm install clean-webpack-plugin -D
複製代碼

修改 webpack.config.js 文件

const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
  plugins: [new CleanWebpackPlugin(['dist'])]
}
複製代碼

提取公用代碼

假如你 a.jsb.js 都 import 了 c.js 文件,這段代碼就冗雜了。爲何要提取公共代碼,簡單來講,就是減小代碼冗餘,提升加載速度。

module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          // 抽離本身寫的公共代碼
          chunks: 'initial',
          name: 'common', // 打包後的文件名,任意命名
          minChunks: 2, //最小引用2次
          minSize: 0 // 只要超出0字節就生成一個新包
        },
        styles: {
          name: 'styles', // 抽離公用樣式
          test: /\.css$/,
          chunks: 'all',
          minChunks: 2,
          enforce: true
        },
        vendor: {
          // 抽離第三方插件
          test: /node_modules/, // 指定是node_modules下的第三方包
          chunks: 'initial',
          name: 'vendor', // 打包後的文件名,任意命名
          // 設置優先級,防止和自定義的公共代碼提取時被覆蓋,不進行打包
          priority: 10
        }
      }
    }
  }
}
複製代碼

hash

hash 是幹嗎用的? 咱們每次打包出來的結果可能都是同一個文件,那我上線的時候是否是要替換掉上線的 js,那我怎麼知道哪是最新的呢,咱們通常會清一下緩存。而 hash 就是爲了解決這個問題而存在的

咱們此時在改一些 webpack.config.js 的配置

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash:8].js'
  },
  //...
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[hash:8].css',
      chunkFilename: '[id].[hash:8].css'
    })
  ]
}
複製代碼

減小 resolve 的解析,配置別名

若是咱們能夠精簡 resolve 配置,讓 webpack 在查詢模塊路徑時儘量快速地定位到須要的模塊,不作額外的查詢工做,那麼 webpack 的構建速度也會快一些

module.exports = {
  resolve: {
    /** * alias: 別名的配置 * * extensions: 自動解析肯定的擴展, * 好比 import 'xxx/theme.css' 能夠在extensions 中添加 '.css', 引入方式則爲 import 'xxx/theme' * @default ['.wasm', '.mjs', '.js', '.json'] * * modules 告訴 webpack 解析模塊時應該搜索的目錄 * 若是你想要添加一個目錄到模塊搜索目錄,此目錄優先於 node_modules/ 搜索 * 這樣配置在某種程度上能夠簡化模塊的查找,提高構建速度 @default node_modules 優先 */
    alias: {
      '@': path.resolve(__dirname, 'src'),
      tool$: path.resolve(__dirname, 'src/utils/tool.js') // 給定對象的鍵後的末尾添加 $,以表示精準匹配
    },
    extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx'],
    modules: [path.resolve(__dirname, 'src'), 'node_modules']
  }
}
複製代碼

webpack-dev-serve

上面講到了都是如何打包文件,可是開發中咱們須要一個本地服務,這時咱們可使用 webpack-dev-server 在本地開啓一個簡單的靜態服務來進行開發。

webpack-dev-server 是 webpack 官方提供的一個工具,能夠基於當前的 webpack 構建配置快速啓動一個靜態服務。當 modedevelopment 時,會具有 hot reload 的功能,即當源碼文件變化時,會即時更新當前頁面,以便你看到最新的效果。...

npm install webpack-dev-server -D
複製代碼

package.json 中 scripts 中添加

"start": "webpack-dev-server --mode development"
複製代碼

默認開啓一個本地服務的窗口 http://localhost:8080/ 便於開發

配置開發服務器

咱們能夠對 webpack-dev-server 作針對性的配置

module.exports = {
  // 配置開發服務器
  devServer: {
    port: 1234,
    open: true, // 自動打開瀏覽器
    compress: true // 服務器壓縮
    //... proxy、hot
  }
}
複製代碼
  • contentBase: 服務器訪問的根目錄(可用於訪問靜態資源)
  • port: 端口
  • open: 自動打開瀏覽器

模塊熱替換(hot module replacement)

模塊熱替換(HMR - Hot Module Replacement)功能會在應用程序運行過程當中替換、添加或刪除模塊,而無需從新加載整個頁面。主要是經過如下幾種方式,來顯著加快開發速度:

  • 保留在徹底從新加載頁面時丟失的應用程序狀態。
  • 只更新變動內容,以節省寶貴的開發時間。
  • 調整樣式更加快速 - 幾乎至關於在瀏覽器調試器中更改樣式。

上面咱們 npm start 後修改一次文件,頁面就會刷新一次。這樣就存在很大問題了,好比咱們使用 redux, vuex 等插件,頁面一刷新那麼存放在 redux, vuex 中的東西就會丟失,很是不利於咱們的開發。

HMR 配合 webpack-dev-server ,首先咱們配置下 webpack.config.js

const webpack = require('webpack')

module.exports = {
  devServer: {
    //...
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
    //...
  ]
}
複製代碼

配置後還不行,由於 webpack 還不知道你要更新哪裏, 修改 src/index.js 文件, 添加

if (module.hot) {
  module.hot.accept()
}
複製代碼

重啓服務,npm start 以後,修改引入 index.js 文件後,頁面就不會從新刷新了,這便實現了 HMR

可是可是有個問題是,你修改 css/less 等樣式文件並未發生改變, what ?

HMR 修改樣式表 須要藉助於 style-loader, 而咱們以前用的是 MiniCssExtractPlugin.loader, 這也好辦,修改其中一個 rules 就能夠了,咱們能夠試試改

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          // MiniCssExtractPlugin.loader,
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [require('autoprefixer')] // 添加css中的瀏覽器前綴
            }
          },
          'less-loader'
        ]
      }
    ]
  }
}
複製代碼

這樣咱們修改 less 文件就會發現 HMR 已經實現了。

其實,咱們能夠發現,dev 下配置的 loader 爲 style-loader , 而生產環境下則是須要 MiniCssExtractPlugin.loader

這就涉及到了不一樣環境之間的配置。能夠經過 process.env.NODE_ENV 獲取當前是開發環境或者是生產環境,而後配置不一樣的 loader,這裏就不作展開了。下一篇文章打算在作一個 react-cli 或者 vue-cli 的配置,將開發環境的配置與生產環境的配置分開爲不一樣的文件。

結語

前面講到的知識都是 webpack 的一些基礎的知識,更多的資料能夠查詢webpack 中文官網,官網講的比較詳細,我這裏也是講最常的配置,也是一篇入門系列的文章,文中涉及的知識點還有不少地方還須要完善,譬如 優化 webpack 的構建速度, 減少打包的體積等等。

學習 webpack 4.0 還須要多實踐,多瞎搞,筆者也是剛剛學習 webpack 的配置,不對之處請各位指出。

下一篇文章打算從零配置一個腳手架,以加深本身對 webpack 的理解。

本文產生的代碼:webpack-dev

參考

相關文章
相關標籤/搜索