webpack:從入門到真實項目配置

簡單使用

安裝

在命令行中依次輸入

mkdir  webpack-demo
cd webpack-demo
// 創建 package.json,這裏會問一些問題,直接回車跳過就行
npm init 
//  推薦這個安裝方式,當然你也安裝在全局環境下
// 這種安裝方式會將 webpack 放入 devDependencies 依賴中
npm install --save-dev webpack

然後按照下圖創建文件

在以下文件寫入代碼

// sum.js
// 這個模塊化寫法是 node 環境獨有的,瀏覽器原生不支持使用
module.exports = function(a, b) {
    return a + b
}
// index.js
var sum = require('./sum')
console.log(sum(1, 2))
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script src="./build/bundle.js"></script>
</body>
</html>

現在我們開始配置最簡單的 webpack,首先創建 webpack.config.js 文件,然後寫入如下代碼

// 自帶的庫
const path = require('path')
module.exports = {
    entry:  './app/index.js', // 入口文件
    output: {
      path: path.resolve(__dirname, 'build'), // 必須使用絕對地址,輸出文件夾
      filename: "bundle.js" // 打包後輸出文件的文件名
    }
  }

現在我們可以開始使用 webpack 了,在命令行中輸入

node_modules/.bin/webpack

沒問題的話你應該可以看到類似的樣子

可以發現原本兩個 JS 文件只有 100B,但是打包後卻增長到 2.66KB,這之中 webpack 肯定做了什麼事情,我們去 bundle.js 文件中看看。

把代碼簡化以後,核心思路是這樣的

var array = [(function () {
        var sum = array[1]
        console.log(sum(1, 2))
    }),
    (function (a,b) {
        return a + b
    })
]
array[0]() // -> 3

因爲 module.export 瀏覽器是不支持的,所以 webpack 將代碼改成瀏覽器能識別的樣子。現在將 index.html 文件在瀏覽器中打開,應該也可以看到正確的 log。

我們之前是在文件夾中安裝的 webpack,每次要輸入 node_modules/.bin/webpack 過於繁瑣,可以在 package.json 如下修改

"scripts": {
    "start": "webpack"
  },

然後再次執行 npm run start,可以發現和之前的效果是相同的。簡單的使用到此爲止,接下來我們來探索 webpack 更多的功能。

Loader

Loader 是 webpack 一個很強大功能,這個功能可以讓你使用很多新的技術。

Babel

Babel 可以讓你使用 ES2015/16/17 寫代碼而不用顧忌瀏覽器的問題,Babel 可以幫你轉換代碼。首先安裝必要的幾個 Babel 庫

npm i --save-dev babel-loader babel-core babel-preset-env

先介紹下我們安裝的三個庫

  • babel-loader 用於讓 webpack 知道如何運行 babel
  • babel-core 可以看做編譯器,這個庫知道如何解析代碼
  • babel-preset-env 這個庫可以根據環境的不同轉換代碼

接下來更改 webpack-config.js 中的代碼

module.exports = {
// ......
    module: {
        rules: [
            {
            // js 文件才使用 babel
                test: /\.js$/,
             // 使用哪個 loader
                use: 'babel-loader',
            // 不包括路徑
                exclude: /node_modules/
            }
        ]
    }
}

配置 Babel 有很多方式,這裏推薦使用 .babelrc 文件管理。

// ..babelrc
{
    "presets": ["babel-preset-env"]
}

現在將之前 JS 的代碼改成 ES6 的寫法

// sum.js
export default (a, b) => {
    return a + b
}
// index.js
import sum from './sum'
console.log(sum(1, 2))

執行 npm run start,再觀察 bundle.js 中的代碼,可以發現代碼被轉換過了,並且同樣可以正常 輸出3。

當然 Babel 遠不止這些功能,有興趣的可以前往官網自己探索。

處理圖片

這一小節我們將使用 url-loader 和 file-loader,這兩個庫不僅可以處理圖片,還有其他的功能,有興趣的可以自行學習。

先安裝庫

npm i --save-dev url-loader file-loader

創建一個 images 文件夾,放入兩張圖片,並且在 app 文件夾下創建一個 js 文件處理圖片
,目前的文件夾結構如圖

// addImage.js
let smallImg = document.createElement('img')
// 必須 require 進來
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)

let bigImg = document.createElement('img')
bigImg.src = require('../images/big.jpeg')
document.body.appendChild(bigImg)

接下來修改 webpack.config.js 代碼

module.exports = {
// ...
    module: {
        rules: [
            // ...
            {
            // 圖片格式正則
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: [
                  {
                    loader: 'url-loader',
                    // 配置 url-loader 的可選項
                    options: {
                    // 限制 圖片大小 10000B,小於限制會將圖片轉換爲 base64格式
                      limit: 10000,
                    // 超出限制,創建的文件格式
                    // build/images/[圖片名].[hash].[圖片格式]
                      name: 'images/[name].[hash].[ext]'
                   }
                  }
                ]
            }
        ]
    }
  }

運行 npm run start,打包成功如下圖

可以發現大的圖片被單獨提取了出來,小的圖片打包進了 bundle.js 中。

在瀏覽器中打開 HTML 文件,發現小圖確實顯示出來了,但是卻沒有看到大圖,打開開發者工具欄,可以發現我們大圖的圖片路徑是有問題的,所以我們又要修改 webpack.config.js 代碼了。

module.exports = {
    entry:  './app/index.js', // 入口文件
    output: {
      path: path.resolve(__dirname, 'build'), // 必須使用絕對地址,輸出文件夾
      filename: "bundle.js", // 打包後輸出文件的文件名
      publicPath: 'build/' // 知道如何尋找資源
    }
    // ...
  }

最後運行下 npm run start,編譯成功了,再次刷新下頁面,可以發現這次大圖被正確的顯示了。下一小節我們將介紹如何處理 CSS 文件。

處理 CSS 文件

添加 styles 文件夾,新增 addImage.css 文件,然後在該文件中新增代碼

img {
    border: 5px black solid;
}
.test {border: 5px black solid;}

這一小節我們先使用 css-loader 和 style-loader 庫。前者可以讓 CSS 文件也支持impost,並且會解析 CSS 文件,後者可以將解析出來的 CSS 通過標籤的形式插入到 HTML 中,所以後面依賴前者。

npm i --save-dev css-loader style-loader

首先修改 addImage.js 文件

import '../styles/addImage.css'

let smallImg = document.createElement('img')
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)

// let bigImg = document.createElement('img')
// bigImg.src = require('../images/big.jpeg')
// document.body.appendChild(bigImg)

然後修改 webpack.config.js 代碼

module.exports = {
// ...
    module: {
      rules: [
        {
            test: /\.css$/,
            use: ['style-loader',
                {
                    loader: 'css-loader',
                    options: {
                        modules: true
                       }
                }
            ]
        },
      ]
    }
  }

運行下 npm run start,然後刷新頁面,可以發現圖片被正確的加上了邊框,現在我們來看一下 HTML 的文件結構

從上圖可以看到,我們在 addImage.css 文件中寫的代碼被加入到了 style 標籤中,並且因爲我們開啓了 CSS 模塊化的選項,所以 .test 被轉成了唯一的哈希值,這樣就解決了 CSS 的變量名重複問題。

但是將 CSS 代碼整合進 JS 文件也是有弊端的,大量的 CSS 代碼會造成 JS 文件的大小變大,操作 DOM 也會造成性能上的問題,所以接下來我們將使用 extract-text-webpack-plugin插件將 CSS 文件打包爲一個單獨文件

首先安裝 npm i --save-dev extract-text-webpack-plugin

然後修改 webpack.config.js 代碼

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

module.exports = {
// ....
    module: {
      rules: [
        {
          test: /\.css$/,
          // 寫法和之前基本一致
          loader: ExtractTextPlugin.extract({
          // 必須這樣寫,否則會報錯
                fallback: 'style-loader',
                use: [{
                    loader: 'css-loader',
                    options: { 
                        modules: true
                    }
                }]
            })
        ]
        }
      ]
    },
    // 插件列表
    plugins: [
    // 輸出的文件路徑
      new ExtractTextPlugin("css/[name].[hash].css")
    ]
  }

運行下 npm run start,可以發現 CSS 文件被單獨打包出來了

但是這時候刷新頁面會發現圖片的邊框消失了,那是因爲我們的 HTML 文件沒有引用新的 CSS 文件,所以這裏需要我們手動引入下,在下面的章節我們會通過插件的方式自動引入新的文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章