webpack學習筆記:搭建基本的前端開發環境

blacker2018發表於2018-07-02

完成日常中需要的基礎前端構建需求:構建 HTML、CSS、JS 檔案、使用 CSS 前處理器來編寫樣式、處理和壓縮圖片、使用 Babel、方便開發除錯的靜態服務

安裝和使用

我們使用 npm 或者 yarn 來安裝 webpack,可以作為一個全域性的命令來使用:

npm install webpack webpack-cli -g 

# 或者
yarn global add webpack webpack-cli

# 然後就可以全域性執行命令了
webpack --help
複製程式碼

webpack-cli 是使用 webpack 的命令列工具,在 4.x 版本之後不再作為 webpack 的依賴了,我們使用時需要單獨安裝這個工具。

在專案中,我們更多地會把 webpack 作為專案的開發依賴來安裝使用,這樣可以指定專案中使用的 webpack 版本,更加方便多人協同開發:

確保你的專案中有 package.json 檔案,如果沒有可以使用 npm init 來建立。

npm install webpack -D  # -D 表示安裝 webpack 並新增到開發依賴中(devDependencies)

# 或者
yarn add webpack -D
複製程式碼

這樣 webpack 會出現在 package.json 中,我們再新增一個 npm scripts:

  "scripts": {
    "build": "webpack --mode production"
  },
  "devDependencies": {
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.12",
  }
複製程式碼

然後我們建立一個 ./src/index.js 檔案,可以寫任意的 JS 程式碼。建立好了之後執行 npm run build 或者 yarn build 命令,你就會發現新增了一個 dist 目錄,裡邊存放的是 webpack 構建好的 main.js 檔案。

因為是作為專案依賴進行安裝,所以不會有全域性的命令,npm/yarn 會幫助我們在當前專案依賴中尋找對應的命令執行,如果是全域性安裝的 webpack,直接執行 webpack --mode production 就可以。

webpack 4.x 的版本可以零配置就開始進行構建,但是筆者覺得這個功能還不全面,缺少很多實際專案需要的功能,所以基本你還是需要一個配置檔案。

需求分析

我們日常使用的前端開發環境應該是怎樣的?我們可以嘗試著把基本前端開發環境的需求列一下:

  • 構建我們釋出需要的 HTML、CSS、JS 檔案
  • 使用 CSS 前處理器來編寫樣式
  • 處理和壓縮圖片
  • 使用 Babel 來支援 ES 新特性
  • 本地提供靜態服務以方便開發除錯

上述幾項應該可以滿足比較簡單的前端專案開發環境需求了,下面會一一介紹如何配置 webpack 來滿足這些需求。

關聯 HTML

webpack 預設從作為入口的 .js 檔案進行構建(更多是基於 SPA 去考慮),但通常一個前端專案都是從一個頁面(即 HTML)出發的,最簡單的方法是,建立一個 HTML 檔案,使用 script 標籤直接引用構建好的 JS 檔案,如:

<script src="./dist/bundle.js"></script>
複製程式碼

但是,如果我們的檔名或者路徑會變化,例如使用 [hash] 來進行命名,那麼最好是將 HTML 引用路徑和我們的構建結果關聯起來,這個時候我們可以使用 html-webpack-plugin

html-webpack-plugin 是一個獨立的 node package,所以在使用之前我們需要先安裝它,把它安裝到專案的開發依賴中:

npm install html-webpack-plugin -D 

# 或者
yarn add html-webpack-plugin -D
複製程式碼

然後在 webpack 配置中,將 html-webpack-plugin 新增到 plugins 列表中:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin(),
  ],
}
複製程式碼

這樣配置好之後,構建時 html-webpack-plugin 會為我們建立一個 HTML 檔案,其中會引用構建出來的 JS 檔案。實際專案中,預設建立的 HTML 檔案並沒有什麼用,我們需要自己來寫 HTML 檔案,可以通過 html-webpack-plugin 的配置,傳遞一個寫好的 HTML 模板:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置輸出檔名和路徑
      template: 'assets/index.html', // 配置檔案模板
    }),
  ],
}
複製程式碼

這樣,通過 html-webpack-plugin 就可以將我們的頁面和構建 JS 關聯起來,迴歸日常,從頁面開始開發。如果需要新增多個頁面關聯,那麼例項化多個 html-webpack-plugin, 並將它們都放到 plugins 欄位陣列中就可以了。

更多配置這裡就不展開講解了,參考文件 html-webpack-plugin 以及官方提供的例子 html-webpack-plugin/examples

構建 CSS

我們編寫 CSS,並且希望使用 webpack 來進行構建,為此,需要在配置中引入 loader 來解析和處理 CSS 檔案:

module.exports = {
  module: {
    rules: [
      // ...
      {
        test: /\.css/,
        include: [
          path.resolve(__dirname, 'src'),
        ],
        use: [
          'style-loader',
          'css-loader',
        ],
      },
    ],
  }
}
複製程式碼

注意:style-loader 和 css-loader 都是單獨的 node package,需要安裝。

我們建立一個 index.css 檔案,並在 index.js 中引用它,然後進行構建。

import "./index.css"
複製程式碼

可以發現,構建出來的檔案並沒有 CSS,先來看一下新增兩個 loader 的作用:

css-loader 負責解析 CSS 程式碼,主要是為了處理 CSS 中的依賴,例如 @importurl() 等引用外部檔案的宣告; style-loader 會將 css-loader 解析的結果轉變成 JS 程式碼,執行時動態插入 style 標籤來讓 CSS 程式碼生效。 經由上述兩個 loader 的處理後,CSS 程式碼會轉變為 JS,和 index.js 一起打包了。如果需要單獨把 CSS 檔案分離出來,我們需要使用 extract-text-webpack-plugin 外掛。

extract-text-webpack-plugin 這個外掛在筆者寫作時並未釋出支援 webpack 4.x 的正式版本,所以安裝的時候需要指定使用它的 alpha 版本:npm install extract-text-webpack-plugin@next -D 或者 yarn add extract-text-webpack-plugin@next -D。如果你用的是 webpack 3.x 版本,直接用 extract-text-webpack-plugin 現有的版本即可。

看一個簡單的例子:

const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        // 因為這個外掛需要干涉模組轉換的內容,所以需要使用它對應的 loader
        use: ExtractTextPlugin.extract({ 
          fallback: 'style-loader',
          use: 'css-loader',
        }), 
      },
    ],
  },
  plugins: [
    // 引入外掛,配置檔名,這裡同樣可以使用 [hash]
    new ExtractTextPlugin('index.css'),
  ],
}
複製程式碼

CSS 前處理器

在上述使用 CSS 的基礎上,通常我們會使用 Less/Sass 等 CSS 前處理器,webpack 可以通過新增對應的 loader 來支援,以使用 Less 為例,我們可以在官方文件中找到對應的 loader。

我們需要在上面的 webpack 配置中,新增一個配置來支援解析字尾為 .less 的檔案:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.less$/,
        // 因為這個外掛需要干涉模組轉換的內容,所以需要使用它對應的 loader
        use: ExtractTextPlugin.extract({ 
          fallback: 'style-loader',
          use: [
            'css-loader', 
            'less-loader',
          ],
        }), 
      },
    ],
  },
  // ...
}
複製程式碼

處理圖片檔案

在前端專案的樣式中總會使用到圖片,雖然我們已經提到 css-loader 會解析樣式中用 url() 引用的檔案路徑,但是圖片對應的 jpg/png/gif 等檔案格式,webpack 處理不了。是的,我們只要新增一個處理圖片的 loader 配置就可以了,現有的 file-loader 就是個不錯的選擇。

file-loader 可以用於處理很多型別的檔案,它的主要作用是直接輸出檔案,把構建後的檔案路徑返回。配置很簡單,在 rules 中新增一個欄位,增加圖片型別檔案的解析配置:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {},
          },
        ],
      },
    ],
  },
}
複製程式碼

更多關於 file-loader 的配置可以參考官方文件 file-loader

使用 Babel

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

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.jsx?/, // 支援 js 和 jsx
        include: [
          path.resolve(__dirname, 'src'), // src 目錄下的才需要經過 babel-loader 處理
        ],
        loader: 'babel-loader',
      },
    ],
  },
}
複製程式碼

Babel 的相關配置可以在目錄下使用 .babelrc 檔案來處理,詳細參考 Babel 官方文件 .babelrc

啟動靜態服務

至此,我們完成了處理多種檔案型別的 webpack 配置。我們可以使用 webpack-dev-server 在本地開啟一個簡單的靜態服務來進行開發。

在專案下安裝 webpack-dev-server,然後新增啟動命令到 package.json 中:

"scripts": {
  "build": "webpack --mode production",
  "start": "webpack-dev-server --mode development"
}
複製程式碼

也可以全域性安裝 webpack-dev-server,但通常建議以專案開發依賴的方式進行安裝,然後在 npm package 中新增啟動指令碼。

嘗試著執行 npm run start 或者 yarn start,然後就可以訪問 http://localhost:8080/ 來檢視你的頁面了。預設是訪問 index.html,如果是其他頁面要注意訪問的 URL 是否正確。

相關文章