Hello, Webpack!

掘金5025發表於2018-03-12

前言

“模組化”可以說是現在前端最流行的三個字,而webpack就是一款非常非常流行的模組打包工具,它可以分析模組之間的依賴關係,並將這些模組根據指定規則打包成瀏覽器能識別的靜態資源。

作為一個前端,學習並使用webpack已經是刻不容緩的事情,現在,就讓我們開始webpack之旅吧。

安裝webpack

首先新建一個空的資料夾,使用npm init命令初始化。

初始化的目的是為了生成package.json檔案,這是一個npm說明檔案,裡面包含了當前專案的依賴模組,自定義的指令碼任務等資訊。

//新建webpack-demo的資料夾
mkdir webpack-demo
//進入該資料夾
cd webpack-demo
// 初始化
npm init
複製程式碼

輸入npm init命令後,終端會要求你填寫一些資訊,如果你不準備在npm中釋出你的模組,直接一路回車完成初始化就行。

初始化完成後,你可以看到已經生成了一個package.json檔案,你也可以在這個檔案裡手動修改初始化的時候終端讓你輸入的資訊。

接下來就要安裝webpack,你可以全域性安裝webpack,也可以在專案目錄下安裝webpack,官方不支援全域性安裝,因為那樣會使不同webpack版本的專案搭建失敗。

// 全域性安裝
npm install -g webpack
// 安裝到指定專案目錄
npm install --save-dev webpack
複製程式碼

安裝完成後我們發現專案目錄中多了一個node_modules資料夾,我們可以檢視下webpack的版本。

// 檢視全域性安裝的webpack版本
webpack -v
// 檢視非全域性安裝的webpack版本
cd node_modules/.bin
webpack -v
複製程式碼

接下來我們開始用webpack來打包第一個檔案。

打包第一個檔案

用編輯器開啟專案,新建一個hello.js檔案。

Hello, Webpack!

使用webpack打包hello.js檔案,同樣,不是全域性安裝webpack的小夥伴們這時得注意路徑問題了。

// 全域性安裝webpack的情況
webpack hello.js bundle.js
// 非全域性安裝webpack的情況
cd node_modules/.bin
webpack [完整路徑]/hello.js [完整路徑]/bundle.js
複製程式碼

Hello, Webpack!

如圖所示,打包完成後,webpack會告訴我們一些資訊,比如打包時間、打包後檔案的大小等。

這時我們發現,如果不是全域性安裝webpack,執行webpack打包命令將變得非常麻煩,其實我們可以配合npm的指令碼來更快捷的執行打包任務。

Hello, Webpack!

修改package.json檔案,在scripts屬性中新增執行webpack打包的指令碼,比如build,執行npm run build hello.js bundle.js,發現打包成功。

Hello, Webpack!

打包好之後我們可以通過live-server啟動一個本地服務。

// 全域性安裝live-server
$ npm install -g live-server
複製程式碼

安裝好之後執行live-server,會發現它已經幫我們開啟了一個瀏覽器頁面,並且當你修改本地任何檔案時,瀏覽器都會自動更新。

Hello, Webpack!

現在我們已經成功打包了一個js檔案,接下來讓我們試著打包一個css檔案。

新建一個index.html檔案和style.css檔案,在樣式檔案中新增一些樣式,並在hello.js檔案裡用require的方式將其引入(require是CommonJS的語法,webpack支援CommonJS/AMD/CMD)。

這時如果我們直接打包會發現報錯了,錯誤提示我們需要一個合適的loader來處理這種css檔案型別。因此我們要先安裝兩個loader,css-loader和style-loader,前者是使webpack支援css檔案,後者則會將樣式通過style標籤插入到html中。

npm install css-loader style-loader --save-dev
複製程式碼

安裝完成後,我們還需要在檔案引用的地方指定相應的loader。

require('style-loader!css-loader!./style.css')
複製程式碼

再次執行打包命令發現打包成功,在index.html裡引入打包好的bundle.js,開啟index.html頁面發現樣式已經成功顯示。

// 檔案更新的時候自動打包
webpack {entry file} {bundled file} --watch
// 顯示檔案打包的過程
webpack {entry file} {bundled file} --progress
// 顯示所有模組
webpack {entry file} {bundled file} --display-modules
// 顯示打包模組的原因
webpack {entry file} {bundled file} --display-reasons
複製程式碼

webpack配置檔案

webpack有非常多的功能,因此我們需要有一份好的配置檔案來放置所有的打包配置資訊。

Hello, Webpack!

如圖所示,構建一份新的目錄,src資料夾用來放打包前的資源,dist資料夾用來放打包後的資源,webpack.config.js用來配置打包資訊,如果配置檔案不叫webpack.config.js,則打包的時候需要用--config來重新指定,比如

webpack --config webpack.config.a.js
複製程式碼

入口(Entry)和出口(Output)

Hello, Webpack!

入口(enrty),簡單來說,就是告訴webpack從哪裡開始。我們可以通過在webpack配置中配置entry屬性,來指定一個入口起點(或多個入口起點)。webpack會根據這個入口,來獲取模組之間的依賴關係並根據依賴關係來知道需要繫結些什麼。

出口(output),用來告訴webpack打包後檔案做何處理及存放的位置。如上圖所示,output.filename 指定了打包後的檔案的名字,output.path則指定了檔案存放的位置。

關於path獲取到的絕對路徑,我們可以新建一個js檔案輸入該路徑,並用node執行這個js檔案。

Hello, Webpack!

入口(Entry)

  • 單個入口寫法

Hello, Webpack!

entry屬性的單個入口語法,是下面這種的簡寫方式:

Hello, Webpack!

  • 物件語法

Hello, Webpack!

出口(Output)

  • 單個入口起點

Hello, Webpack!

  • 多個入口起點

Hello, Webpack!

如果在打包生成的檔名後面加上不確定的chunkhash,這時候我們需要藉助webpack的外掛html-webpack-plugin來自動生成專案中的html頁面。

// 通過npm安裝
$ npm install html-webpack-plugin --save-dev 
複製程式碼

Hello, Webpack!

Loader

loader用於對模組的原始碼進行轉換。它可以將不同語言的檔案轉換為JavaScript,或將圖片轉換為dataURL等。

安裝babel:

$ npm install --save-dev babel-loader babel-core babel-preset-latest
複製程式碼

指示webpack對每個.js結尾的檔案使用babel-loader進行轉換:

module: {
    loaders: [
        {
            test: /\.js$/,
            loader: 'babel-loader',
            include: path.resolve(__dirname, 'src'),
            exclude: path.resolve(__dirname, 'node_modules'),
            query: {
                presets: ['latest']
            }
        }
    ]
}
複製程式碼
  • 其他檔案型別
loaders: [
    {
        test: /\.js$/,
        loader: 'babel-loader',
        include: path.resolve(__dirname, 'src'),
        exclude: path.resolve(__dirname, 'node_modules'),
        query: {
            presets: ['latest']
        }
    },
    {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
    },
    {
        test: /\.less$/,
        loader: 'style-loader!css-loader!less-loader'
    },
    {
        test: /\.(png|jpg|gif|svg)$/i,
        loaders: [
            'url-loader?limit=10000&name=assets/[name]-[hash:5].[ext]',
            'image-webpack-loader'
        ]
    }
]
複製程式碼