Webpack4 入門到帶你打包一個簡單單頁應用專案

緣氏集團技術員發表於2018-10-06
正文前先吐槽下, webpack 對新手入門真的有點不友好,各個版本在配置上都有或多或少的差異,導致在對照各種教程學習的過程中免不了掉進各種坑裡,所以寫這篇文章旨在簡單明瞭的解釋說明 webpack 的各種常用配置,希望能讓新人接觸 webpack 時少走些彎路。

一、搭建專案

1. 我們先新建一個專案 project 並用 npm 命令初始化專案(一路回車)
npm init
複製程式碼
2. 安裝 webpack 與 webpack-cli ( 4 版本需要cli才能執行命令)
npm install --save-dev webpack webpack-cli
複製程式碼
3. 新建 src 資料夾,存放我們要打包的原始碼,預設輸入檔案是 index.js,所以我們在 src 下新建一個index.js檔案
document.write("測試檔案打包")
複製程式碼
4. 執行命令,便能實現最簡單的 “ 專案打包 ”
webpack
複製程式碼
5. 輸入命令打包完成後會生成一個 dist 資料夾,裡面就存放著我們需要打包的檔案,這樣一個最簡單的 webpack 打包流程到此完工,接下來就要進入正片了。

二、命令部分

1. webpack 預設打包命令

第一部分我們使用過 webpack 命令進行打包,其實這個命令是不完整的,細心的小夥伴會發現執行時控制檯會有提示該命令有 production(生產) 與 development (開發)模式,完整命令如下:

// 兩個命令有和不同就請大家自己手動試一下,這裡就不贅述了
webpack --mode production
webpack --mode development
複製程式碼
2. webpack 根據配置檔案打包命令

實際中我們打包專案根據需要會有各種配置,因此常用的是根據配置檔案來進行打包,所以我們在專案根目錄下新建一個 webpack.conf.js 檔案來儲存配置資訊

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
  }
}
複製程式碼

稍後會對這個檔案進行詳細講解,這裡先執行命令看是否能成功進行按需打包

// webpack.conf.js 可根據自己需要命名 打包方法是 --config 配置檔案路徑
webpack --mode production --config ./webpack.conf.js
複製程式碼

打包成功會發現在 dist 下現在生成的檔名已經由預設變成了我們指定的 bundle.js

3. 改寫 npm 命令

由於 webpack 指令比較長,輸入時很不方便,我們有個小技巧可以簡化這一步驟,就是對專案的 package.json 檔案中的 script 部分進行修改

  "scripts": {
    "dev": "webpack --mode development --config ./webpack.conf.js",
    "build": "webpack --mode production --config ./webpack.conf.js"
  },
複製程式碼

然後執行以下命令就相當於執行了我們所設定對應的完整 webpack 命令

npm run dev
npm run build
複製程式碼

三、配置部分

這部分會涉及很多內容,包括一些常用外掛,我會逐步帶大家完善 webpack.conf.js 檔案,但基本點到即止,詳細配置還需參考官方文件自行配置

1. 關於檔案路徑

配置檔案會有許多關於檔案路徑的設定,這方面一不小心就會出現問題,這裡推薦採以下方法對相對路徑進行處理

const path = require('path')
// 此方法會根據傳入的相對路徑自動轉化為絕對路徑,確保路徑的正確
path.resolve(__dirname, '檔案的相對路徑')
複製程式碼
  • webpack.conf.js 配置例子
const path = require('path')

module.exports = {
  entry: path.resolve(__dirname, './src/index.js'),
  output: {
    filename: 'main.js',
  }
}
複製程式碼

2. 配置檔案結構總覽

主要包含以下 4 個部分 entry:配置檔案入口 output:配置輸出檔名與路徑 plugins:配置引入的外掛 module: 配置檔案轉換的規則

const path = require('path')

module.exports = {
  // 輸入路徑配置
  entry: path.resolve(__dirname, './src/index.js'),
  // 輸出檔名和路徑配置
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist')
  },
  // 引入外掛配置
  plugins: [],
  // 檔案型別轉換配置
  module: {}
}
複製程式碼

對檔案結構有個總體瞭解後我們接下來就開始逐步完善

3. 完善 js 檔案輸出路徑

通常專案我們有一個專門的 js 資料夾進行存放 js 檔案,並且為了區分版本,我們有時會使用 hash 進行區分( hash 值僅當原始碼檔案被修改時才會更新)

  • webpack.conf.js 配置例子
const path = require('path')

module.exports = {
  // 輸入路徑配置
  entry: path.resolve(__dirname, './src/index.js'),
  // 輸出檔名和路徑配置
  output: {
    // [name] 可自行配置,參考文件
    // [hash:4] 使用 hash 取前 4 位
    filename: 'js/[name]-[hash:4].js',
    path: path.resolve(__dirname, './dist')
  },
  // 引入外掛配置
  plugins: [],
  // 檔案型別轉換配置
  module: {}
}
複製程式碼

4. 使用外掛,引入 html 模板

目前為止,我們打包的都只有 js 檔案,作為前端專案,怎麼可以沒有 html 檔案呢,為了實現打包自動生成 html 檔案,我們開始引入我們的第一個外掛

  • 安裝外掛 html-webpack-plugin
npm install --save-dev html-webpack-plugin
複製程式碼
  • 在專案根目錄下新建 index.html 檔案作為模板,供配置檔案引入
  • webpack.conf.js 配置例子
const path = require('path')
const htmlWebpackPlugins = require('html-webpack-plugin')

module.exports = {
  // 輸入路徑配置
  entry: path.resolve(__dirname, './src/index.js'),
  // 輸出檔名和路徑配置
  output: {
    filename: 'js/main.js',
    path: path.resolve(__dirname, './dist')
  },
  // 引入外掛配置
  plugins: [
    new htmlWebpackPlugins({
      // 輸出檔名
      filename: 'index.html',
      // 所引用模板檔案位置
      template: 'index.html',
      // js 檔案插入的位置
      inject: 'body'
    }),
  ],
  // 檔案型別轉換配置
  module: {}
}
複製程式碼

現在嘗試下打包,基本的 html 和 js 檔案就有了,但這遠遠還不夠,我們還需要對 html 與 js 的相關配置進行處理,為了使專案更完整,我們還要新建一些檔案。

5. 完善專案目錄

  • 在 src 目錄下新建 components 資料夾,分別新建 html, js, css 檔案 ,下面以 scroll 元件為例

scroll.html

<div class="scroll">
  <p>scroll</p>
</div>
複製程式碼

scroll.js

// import tpl from './scroll.html'
// import './scroll.css'

function scroll () {
  return {
    name: 'scroll',
    // tpl: tpl
  }
}

export default scroll
複製程式碼

scroll.css

.scroll {
  height: 500px;
  width: 500px;
  background: red;
}

.scroll p {
  display: flex;
}
複製程式碼
  • 檔案新建完還需在我們的入口檔案 index.js 中引入
import Scroll from './components/scroll'

const App = function () {
  var dom = document.getElementById('app')
  var scroll = new Scroll()
  dom.innerHTML = scroll.tpl
  document.write(scroll.name)
}

new App()
複製程式碼
  • 最後修改下我們的 index.html 模板,新增 app 模組
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>
複製程式碼

這時嘗試打包,便可把我們新增的 scroll.js 引入進來了,但是這時我們 tpl 也就是 scroll.html 還處於註釋狀態,想要正確引入,還需新增其他外掛

6. 使用外掛,配對 .html 型別檔案(之後的 .css, .png等其他型別的檔案引入方法與此類似)

  • 安裝外掛 html-loader
npm install --save-dev html-loader
複製程式碼
  • 修改我們的 webpack.conf.js ,在 module 中完善我們的檔案轉換配置
const path = require('path')
const htmlWebpackPlugins = require('html-webpack-plugin')

module.exports = {
  entry: path.resolve(__dirname, './src/index.js'),
  output: {
    filename: 'js/main.js',
    path: path.resolve(__dirname, './dist')
  },
  plugins: [
    new htmlWebpackPlugins({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
  ],
  // 檔案型別轉換配置
  module: {
    rules: [
      {
        // 正則匹配 html 檔案
        test: /\.html$/,
        use: [
          {
            // 引入 html 檔案載入外掛
            loader: 'html-loader'
          }
        ]
      }
    ]
  }
}
複製程式碼
  • 修改下我們的 scroll.js 檔案,將之前的註釋取消
import tpl from './scroll.html'
// import './scroll.css'

function scroll () {
  return {
    name: 'scroll',
    tpl: tpl
  }
}

export default scroll
複製程式碼
  • OK ~ 嘗試打包,現在應該就能正確的把 scroll.thml 的內容也打包進去了,成功之後我們就只剩 .css 型別檔案沒有打包進去,那麼繼續我們的配置

7. 使用外掛,配對 .css 型別檔案

  • 安裝外掛 css-loader 與 style-loader
npm install --save-dev css-loader style-loader
複製程式碼
  • 修改我們的 webpack.conf.js, 新增匹配規則
const path = require('path')
const htmlWebpackPlugins = require('html-webpack-plugin')

module.exports = {
  // 輸入路徑配置
  entry: path.resolve(__dirname, './src/index.js'),
  // 輸出檔名和路徑配置
  output: {
    filename: 'js/main.js',
    path: path.resolve(__dirname, './dist')
  },
  // 引入外掛配置
  plugins: [
    new htmlWebpackPlugins({
      filename: 'index.html',
      template: 'index.html',
      inject: 'body'
    }),
  ],
  // 檔案型別轉換配置
  module: {
    rules: [
      {
        // 正則匹配 html 檔案
        test: /\.html$/,
        use: [
          {
            // 引入 html 檔案載入外掛
            loader: 'html-loader'
          }
        ]
      },
      {
        // 正則匹配 css 檔案
        test: /\.css$/,
        use: [
          {
            // 引入 style 檔案載入外掛
            loader: 'style-loader'
          },
          {
            // 引入 css 檔案載入外掛
            loader: 'css-loader'
          }
        ]
      },
    ]
  }
}
複製程式碼
  • 修改下我們的 scroll.js 檔案,將之前 css 的註釋也取消
import tpl from './scroll.html'
import './scroll.css'

function scroll () {
  return {
    name: 'scroll',
    tpl: tpl
  }
}

export default scroll
複製程式碼
  • 進行打包,成功後自己看看效果,這樣一個簡單 webpack 打包流程就已經走完了

至此,相信你對 webpack 的基本工作流程有了一定的瞭解,不過這只是剛剛開始,上面的例子離我們實際工作中的應用還有一段距離,例如 js 沒有實現 ES6 到 ES5 的轉換,css 樣式不是以一個檔案的形式插入,遇到引入圖片檔案時上面的配置會出現錯誤,還有許多我們常用的框架檔案如 vue 等檔案型別要打包時都是需要重新配置的,本文就不再對配置進行深究,只是簡單多介紹一些常用外掛供大家學習瞭解

8. 外掛介紹

  • babel-loader , babel-preset-latest , babel-core 用於ES6 到 ES5 的轉換
  • autoprefixer , postcss-loader 用於 css 根據配置的瀏覽器版本進行自動新增字首
  • less, less-loader 用於試別 less 型別樣式檔案(sass等同理,引入相應外掛進行配置)
  • url-loader 用於載入圖片型別檔案
  • image-webpack-loader 用於優化圖片檔案載入
  • mini-css-extract-plugin 用於分離壓縮 css 檔案

相關文章