webpack4入門和多檔案打包嘗試

genetalks_大資料發表於2019-04-04

簡介

按照webpack官網的說法,webpack本質上是javascript應用程式的靜態資源打包器(static module bundler),它可以將模組按照依賴和規則打包成符合生產環境部署的前端資源。webpack可以將按模組非同步載入按需引用,通過loader的轉換還可以將任何資源看作模組,比如css、圖片、json、commonjs模組、amd模組、es6模組等。如今webpack的大版本更新到4.x了,讓我們看下如何使用。

1.安裝使用

新建一個資料夾,依次執行:

npm init
npm i webpack webpack-cli webpack-server -D
複製程式碼

即可開始使用webpack。在資料夾中新建資料夾 srcdist 和檔案webpack.config.js,其中 src 為打包的源目錄用來存放我們要打包的檔案,dist 為輸出目錄,webpack.config.js 是我們配置webpack打包相關引數的檔案。

  • 專案目錄

webpack4入門和多檔案打包嘗試

  • webpack.config.js
//webpack.config.js
const path = require('path')

module.exports = {
  // 打包模式,可選development和production
  mode: 'development',
  // 配置入口檔案
  entry: './src/index.js',
  // 配置輸出檔案
  output: {
    // 輸出路徑
    path: path.resolve(__dirname, './dist'),
    // 輸出檔名稱
    filename: 'build.js'
  },
  // 模組,可以使用各種loader,比如css轉換,圖片壓縮等
  module: {},
  // 外掛,用於生成模板和其它功能
  plugins: [],
  // 可配置本地的webpack開發服務功能
  devServer: {}
}
複製程式碼

編寫好webpack.config.js之後就使用命令npx webpack開始執行打包了。webpack的打包機制,只能以js檔案為入口,如果你需要打包圖片,css,字型,svg等資源,必須使用es6或commonjs等模組載入規範在入口檔案中引入,否則是沒法進行打包構建的。

  • module和一些loader的使用

module可以使用loader處理引入的模組,支援的模組型別有CoffeeScript,TypeScript,ES5/6,sass,less,stylus。模組的依賴方式有:

1.ES2015 import 語句
2. CommonJS require() 語句
3. AMD definerequire 語句
4. css/sass/less 檔案中的 @import 語句
5. 樣式(url(...))或 HTML 檔案(<img src=...>)中的圖片連結(image url)

下面我用一些loader來介紹module的用法,注意使用loader之前需要使用npm安裝對應的loader(npm i xxx-loader -D)

// webpack.config.js
module.exports = {
  mode: '',
  entry: '',
  output: {},
  module: {
    rules: [
      {
        test: /\.css$/, // 匹配css檔案模組
        use: ['style-loader', 'css-loader'] // 使用對應的loader處理
      },
      {
        test: /\.(png|gif|jpe?g|svg)$/, // 匹配圖片檔案
        use: [{
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]?[hash]',
            // 會輸出類似下面這樣的結果
            // path/to/file.png?e43b20c069c4a01867c31e98cbce33c9
          }
        }]
      },
      {
        test: /\.(html)$/, // 用來匹配html檔案模組(html需要通過外掛引入?),可以將html標籤中引入的圖片資源進行打包
        use: [{
          loader: 'html-loader',
          options: {
            attrs: ['<tag>:<attribute>'] // <tag>為引入圖片的標籤名,<attribute>為引入圖片的屬性名
          }
        }]
      }
    ]
  },
  plugins: [],
  devServer: {}
}
複製程式碼

通過上面例子中幾個loader的使用,大致的介紹了模組的作用和用法。如果沒有你需要的功能,可以去webpack官網上去尋找。

另外還有一個圖片打包url-loader,需要注意它和file-loader的區別。url-loader可以說是file-loader的進一步封裝,可以將圖片轉換為base64格式內聯在程式碼中,這樣可以減少圖片載入的http請求。

  • plugins外掛的使用

plugins也是webpack的重要功能之一,藉助外掛我們可以實現loader無法完成的工作。要使用外掛之前,同樣需要使用npm安裝(npm i xxx -D),並且在webpack.config.js中要引用該外掛。下面我簡單介紹幾個外掛的用法,想要更完整的資料可以訪問webpack外掛

// webpack.config.js
const path = require('path')
// 使用外掛之前需要先載入對應的plugin
const CleanWebpackPlugin = require('clear-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  mode: '',
  entry: {
    a: './src/a.js', // 可以引入多個入口檔案
    b: './src/b.js'
  },
  output: {
    path: path.resolve(__dirname + '/dist/'),
    filename: '[name].[hash:8].js' // 輸出多個結果,檔名帶hash值
  },
  module: {},
  plugins: [
    // 每次構建完成後先清理一遍dist目錄
    new CleanWebpackPlugin(['dist']),
    // 生成html檔案到輸入目錄
    new HtmlWebpackPlugin({
      // 可以以src目錄下的html原始檔為模板
      template: './src/index.html',
      // 在目標目錄下生成目標檔案
      filename: './dist/index.html',
      chunks: ['a', 'b'] // 這個引數配合entry可以將打包的模組以<script></script>的形式載入到html檔案中
    }),
    // 該外掛可以將源目錄中的檔案直接複製到目標目錄中
    new CopyWebpackplugin([{
      from: './src/*.css', // 選擇源目錄下的所有css檔案
      flatten: true // 選擇拷貝檔案還是包括資料夾,預設是false
    }])
  ],
  devServer: {}
}
複製程式碼
  • devServer

devServer可以在本地搭建一個webpack構建服務環境

// webpack.config.js
module.exports = {
  mode: '',
  entry: {},
  output: {},
  module: {},
  plugins: [],
  devServer: {
    contentBase: '/dist', // 服務的內容目錄
    port: 4396, // 搭建在本地的服務的埠號
    compress: true, // 服務開啟gzip壓縮
    open: true // 自動開啟本地瀏覽器
  }
}
複製程式碼

同時將專案目錄下的package.json改寫一下。

// package.json
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "start": "webpack-dev-server", // 開啟本地的webpack開發服務環境
  "build": "webpack" // 執行打包
}
複製程式碼

之後我們就可以執行npm run startnpm run webpack開啟服務,執行打包。

2.多檔案入口打包

多檔案打包的本質就是在入口entry新增多個打包入口,在上面介紹plugins的HtmlWebpackPlugins時就用到了兩個入口。我們自然而然的想到有多少個入口檔案,就在entry裡面新增幾個入口不就好了。這樣雖然可以實現多檔案打包,但是每次我們新加一個入口都要手動新增,非常麻煩。所以我們想辦法匹配獲取到源目錄下的所有的入口檔案,然後新增到entry中即可。

function getEntry () {
  let globPath = 'src/**/*.html' // 匹配src目錄下的所有資料夾中的html檔案
  // (\/|\\\\) 這種寫法是為了相容 windows和 mac系統目錄路徑的不同寫法
  let pathDir = 'src(\/|\\\\)(.*?)(\/|\\\\)' // 路徑為src目錄下的所有資料夾
  let files = glob.sync(globPath)
  let dirname, entries = []
  for (let i = 0; i < files.length; i++) {
    dirname = path.dirname(files[i])
    entries.push(dirname.replace(new RegExp('^' + pathDir), '$2').replace('src/', ''))
  }
  return entries
}

function addEntry () {
  let entryObj = {}
  getEntry().forEach(item => {
    entryObj[item] = resolve(__dirname, 'src', item, 'index.js')
  })
  return entryObj
}
複製程式碼

通過上面兩個方法我們就能獲取到src目錄下的所有入口檔案。下面我們看webpack.config.js如何修改

// ...
{
  // entry: resolve(__dirname, "src/home/index.js")
  // 改為
  entry: addEntry()
  //...
}
// ...

getEntry().forEach(pathname => {
  let conf = {
    filename: pathname.replace('src/', '') + '.html',
    template: path.join(__dirname, 'src', pathname, 'index.html'),
    chunks: Array.call([], pathname)
  }
  webpackconfig.plugins.push(new HtmlWebpackPlugin(conf))
})
複製程式碼

這樣我們就能夠實現自動的匹配所有入口檔案和要生成的html模板檔案,同時在HtmlWebpackPlugin外掛使用時,也自動新增了多個模板入口,在目標目錄下生成多個html檔案。

上面只是大致介紹了多入口的思路,具體程式碼可以看我實現的一個demo多頁面打包

參考文章

webpack文件

webpack4.x入門配置

webpack多入口檔案頁面打包配置

webpack前端多頁專案工程


作者簡介: 宮晨光,人和未來大資料前端工程師。

相關文章