從0開始的Webpack - 寫Demo用的簡單配置

前言

現在的前端,一定都用過Vue或者React,多多少少都有接觸過webpack,我還清楚地記得第一次看Vue的Webpack配置時,彷彿在看天書通常。webpack做爲前端工程化的核心知識之一,由於其功能太多,配置項又多又雜,初學時也比較難啃。css

這是一個面向初學者的webpack系列博文。從0開始,一步步搭建出完整的、適用於常規環境的webpack配置。html

每章都以樹狀結構擴深知識點,儘量的涵蓋更多更深的知識內容,同時保留每一個章節的全部代碼。前端

目錄構建

首先建立一個文件,而後執行 npm initwebpack

隨後建立對應子文件夾git

.webpackLemo // 文件夾
│
│-- config // 存放配置文件
│
│-- public // 存放模板
│
│-- src // 存放入口文件
│
└─- package.json
複製代碼

寫Demo用的簡單配置

咱們有了基本文件夾,接下來開始構建最基本配置,能知足平時寫demo用。github

支持打包

首先安裝webpack工具庫web

npm i webpack webpack-cli算法

建立入口文件npm

// src/index.js

console.log("Webpack Lemo");
複製代碼
// public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Webpack Lemo</title>
</head>
<body>
    <script src="./main.js"></script> //打包後的文件爲 main.js 在這裏手動寫入
</body>
</html>
複製代碼

建立配置文件json

// config/webpack.config.js

const path = require('path');
module.exports = {
    entry: {
        main: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, '../build')
    }
}
複製代碼

entry :入口起點配置。簡單來講,由html直接引用的文件稱爲入口起點,從這個起點開始,應用程序啓動執行。例子中的 main 爲入口起點的 [name] 值

output:輸出配置。webpack打包完成,怎麼輸出,要輸出哪些文件,輸出到哪等相關信息的配置

output.path 要求接受一個絕對路徑。 path.resolve 方法會把一個路徑或路徑片斷的序列解析爲一個絕對路徑,__dirname 指向當前文件的路徑

entry 配置裏使用的是相對路徑,這個路徑默認指向代碼被執行時路徑,即 webpackLemo 文件夾的根目錄。可經過設置 context 來修改路徑上下文。

// 與正文中的配置效果等同
{
    context: path.resolve(__dirname),
	entry: {
        main: '../src/index.js'
    }
}
複製代碼

關於entry的更多信息 關於output的更多信息

// package.json
{
  ...
  "scripts": {
    "dev": "webpack --config ./config/webpack.config.js"
  },
  ...
}
複製代碼

接下來只需在命令行裏執行 npm run dev 就能進行第一次打包

先忽視 warning ,能夠看見webpack自動打包了 src 目錄下的文件,在根目錄下自動生成build文件,並將打包後的入口文件命名爲 main.js 放入build文件中。

而後咱們能夠把 public 目錄下的 index.html 手動複製到 build 目錄下。

完成以上操做後,咱們的目錄會長成這樣

.webpackLemo
│
│-- build // 存放打包後的文件
│  │-- main.js // src/index.js打包生成的文件
│  │-- index.html // 從public中手動複製
│
│-- config
│  │-- webpack.config.js // 新建webpack配置文件
│
│-- public
│  │-- index.html // 新建html模板文件
│
│-- src
│  │-- index.js // 新建入口文件
│
└─- package.json
複製代碼

用瀏覽器打開 ./build/index.html,能夠看見控制檯裏輸出了 在 ./src/index.js 裏寫的 console.log信息

模板處理

若是每次打包,都須要咱們手動粘貼一次 index.html,那也太麻煩了。若是有一個哥們兒能 幫咱們自動複製index.html文件,而且在index.html中自動引入咱們打包後的文件 那就行了。

這個哥們兒叫作 html-webpack-plugin

執行安裝 npm i html-webpack-plugin

而後修改文件

// public/index.html

<!DOCTYPE html>
<html lang="en">
...

<body>
	// <script src="./main.js"></script>  // 刪除手動寫入的 對main.js的引用
</body>
</html>
複製代碼
// config/webpack.config.js

...
// 引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin'); 

module.exports = {
    ...
    output: {
        ...
        filename: '[name].bundle.js',  // 添加filename配置
    },
    plugins: [ // 注意是個數組
        new HtmlWebpackPlugin({  // 在plugin中使用 html-webpack-plugin
            template: './public/index.html' // 配置模板項地址
        }),
    ]
}
複製代碼

plugins:配置webpack插件的地方

關於plugins的更多信息

filename 配置項中使用了[name],這裏的[name]爲輸出的模塊名。除了[name],webpack還提供了別的模板語法,可在這裏找到全部信息 output.filename

如今咱們再執行 npm run dev 能夠看見此次打包生成的文件名爲main.bundle.js,而且 build 目錄下的index.html 文件裏自動引入了 main.bundle.js

完成以上操做後,咱們的目錄會長成這樣

.webpackLemo
│
│-- build 
│  │-- main.js // 第一次打包生成的文件
│  │-- main.bundle.js // 第二次打包生成的文件
│  │-- index.html // 使用 html-webpack-plugin 後生成的html文件
│
...
複製代碼

文件清理

能夠看見第二次打包時,咱們修改了輸出配置,生成了新的文件,可是第一次打包的內容仍是被保留了下來。其實第一次打包的內容已經用不上了,有沒有什麼哥們兒能幫咱們自動刪除不須要的內容?

有,這個哥們兒叫作 clean-webpack-plugin

執行安裝 npm i clean-webpack-plugin

而後修改文件

// config/webpack.config.js

...
// 引入clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    ...
    output: {
        path: path.resolve(__dirname, '../build'),
        filename: '[name].[contenthash].js', // 咱們再修改一次輸出文件名
    },
    plugins: [
        ...
        new CleanWebpackPlugin(); // 使用 clean-webpack-plugin
    ]
}
複製代碼

如今咱們第三次執行 npm run dev ,能夠看見build目錄下頭兩次生成的入口文件都被清除了,只保留了第三次生成的內容。

完成以上操做後,咱們的目錄就長成這樣

.webpackLemo
│
│-- build 
│  │-- main.417cd68a8235c5cd4f89.js // 第三次打包生成的文件
│  │-- index.html
│
...
複製代碼

到目前爲止,已經支持了基本功能打包,下一步來處理css樣式和file文件

打包css和file文件

對css的支持

對css文件的處理有2種方式:

  1. 將css代碼以 <style> 標籤的形式嵌入 html 中

  2. 生成css文件,以 <link> 標籤的形式在 html 中引入

這裏咱們只討論第一種形式,第二種會在 代碼分割(衛星) 中介紹

咱們須要4個插件

  • style-loader (github) 將css代碼以 <style> 標籤的形式嵌入 html 中
  • css-loader (github) 解析經過模塊化引入的css文件
  • postcss-loader (github) 提供預處理css的一些能力,擁有許多子插件,提供了許多能力
  • autoprefixer (github) postcss-loader的子插件,提供廠商前綴自動補全能力,如 -m-

loader和plugin的區別

// 官方文檔原文
While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables.

// 渣譯
loader通常用來轉換某些類型的modules,而插件能夠用來執行更普遍的任務,例如對包的優化、資源管理、環境注入等

// 大白話
loader是一個轉換器,將A文件進行編譯成B文件,好比:將A.less轉換爲A.css,單純的文件轉換過程。
plugin是一個擴展器,豐富了webpack自己,針對是loader結束後,webpack打包的整個過程,它並不直接操做文件,而是基於事件機制工做,會監聽webpack打包過程當中的某些節點,執行普遍的任務
複製代碼

執行安裝 npm i style-loader css-loader postcss-loader autoprefixer

而後修改文件

// ./config/webpack.config.js

...
module.exports = {
    ...
    module: { // 這裏是對象
        rules: [ // 這裏是數組
            { // 數組中的每一個具體配置
                test: /\.css$/, // 匹配 .css文件
                use: [ // 當匹配上 .css 文件後,會依次使用loader進行處理
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: [
                                require('autoprefixer')
                            ]
                        }
                    }
                ]
            }
        ]
    }
}
複製代碼

module:各類模塊應該如何處理,由module進行配置

關於module的更多信息

loader的處理順序爲從下到上。正文中loader處理順序爲:postcss-loader、css-loader、style-loader

// ./src/index.js
import './index.css'

...
複製代碼
// ./src/index.css

body {
    width: 100%;
    height: 200px;
  	background-image: linear-gradient(to right, red , yellow);
}
複製代碼
// ./package.json
{
    ...
    "browserslist": [
        "iOS >= 6",
        "Android >= 4",
        "IE >= 9"
    ]
}
複製代碼

browserslist 用來配置 咱們的應用會在哪些平臺、哪些瀏覽器和瀏覽器版本上使用。 autoprefixer 會讀取該項值,用來以爲須要添加哪些前綴,若是運行在最新的瀏覽器上,也許不會添加相應的前置信息

browserslist 默認值:> 0.5%, last 2 versions, Firefox ESR, not dead

關於browserslist的更多信息

如今執行 npm run dev ,build 目錄裏沒有新增 .css文件,用瀏覽器打開 ./build/index.html 文件,能夠看見背景有個漸變色,從控制檯裏能夠看見樣式代碼以 <style> 標籤的形式嵌入到了html中,而且自帶了廠商前綴

完成以上操做後,咱們的目錄就長成這樣

.webpackLemo
│
│-- src 
│  │-- index.js
│  │-- index.css // 新增長的css代碼
│
...
複製代碼

對less的支持 (非必要)

less其實就是css的預處理器,一些代碼裏可能會用sass,可是原理相似,這裏就用less舉例

在上一節的基礎上,額外安裝一個 less-loader 處理less文件

執行安裝 npm i less-loader

而後修改文件

// ./config/webpack.config.js

...
module.exports = {
    ...
    module: {
        rules: [
            ...
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader',  // 只增長一行less-loader 處理less文件
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: [
                                require('autoprefixer')
                            ]
                        }
                    }
                ]
            }
        ]
    }
}
複製代碼
// ./src/index.js

import './index.less' // 引入less文件

...
複製代碼
// ./src/index.less

body {
    width: 100%;
    height: 200px;
  	background-image: linear-gradient(to right, red , yellow);
}
複製代碼

執行 npm run dev ,獲得的效果和處理css同樣

完成以上操做後,咱們的目錄就長成這樣

.webpackLemo
│
│-- src 
│  │-- index.js
│  │-- index.css
│  │-- index.less
│
...
複製代碼

對file文件的支持

其實只要是文件,均可以處理,這裏用圖片文件舉例

可用2種 loader 進行處理

  • file-loader (github) 解析經過模塊化引入的文件,在打包的時候會獲取打包後的地址,並在代碼中返回這個地址,使得文件能夠被讀取
  • url-loader (github) 做用同file-loader,可是能把文件壓縮成base64的形式,通常用於圖片

這兩個loader做用比較相似,最大的區別在於 file-loader 會生成文件, url-loader 會把文件數據壓縮成base64直接使用,不會生成文件。二者能一塊兒使用,在某些場景下比使用單一loader效果更好,可參考 這篇博文(衛星)

這裏我用file-loader舉例

執行安裝 npm i file-loader

而後修改文件

// ./config/webpack.config.js

...
module.exports = {
    ...
    module: {
        rules: [
            ...
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    'file-loader'
                ]
            }
        ]
    }
}
複製代碼
// ./src/index.js

...
import img from '../statics/imgs/img.jpg'

const myimg = new Image();
myimg.src = img;
document.body.appendChild(myimg);
...
複製代碼

執行 npm run dev ,能夠看見build文件裏增長了打包後的圖片文件,打開 ./build/index.html 後也能看到相應的圖片被掛載到頁面上

完成以上操做後,咱們的目錄就長成這樣

.webpackLemo
│
│-- build 
│  │-- 051fa5032109fbc8005c856a48cf1c52.jpg
│  │-- index.html
│  │-- main.a14556a5d43741e69cdd.js
│
│-- statics // 存放靜態資源
│  │-- imgs // 存放圖片
│  │  │-- img.jpg
│
...
複製代碼

到如今,咱們已經支持css打包和文件打包,本身寫demo時,使用這樣的webpack配置已經OK了,可是我每次改了代碼都要從新執行一次 npm run dev ,真的太麻煩,若是能讓webpack自動刷新頁面就行了。

構建開發環境

讓咱們來構建一個開發環境,讓咱們每次更新的時候,webpack能自動幫咱們打包,而且能實時刷新頁面.

要能實現實時刷新頁面,webpack提供了3種能力

  1. webpack watch mode webpack 觀察模式,最簡單的方法,但功能所以也少了不少
  2. webpack-dev-server 相對簡單的web server,而且具有live reloading(實時從新加載) 功能
  3. webpack-dev-middleware 最複雜的一種,須要本身寫服務配置,但可塑性也最高

關於dev-server的更多信息

關於3種配置的更多信息

這裏咱們採用 webpack-dev-server

執行安裝 npm i webpack-dev-server

而後修改文件

// ./config/webpack.config.js

...
module.exports = {
    mode: 'development', // 設置mode爲'development'模式
    devtool: 'cheap-module-eval-source-map', // 設置source-map
    devServer: {
        contentBase: './build',
        open: true
    },
    ...
}
複製代碼

mode:至關於設置一套預設優化配置,默認爲 none。詳細可查看 官網文檔

devtool:用於配置source-map,用來加強調試能力,不一樣的值會影響構建和重構建的速度。 詳細可查看 官方文檔

// package.json

{
    ...
    "scripts": {
        // 把dev改爲build
        "build": "webpack --config ./config/webpack.config.js",
        // 這裏改爲dev,並使用新命令項
        "dev": "webpack-dev-server --config ./config/webpack.config.js"
	},
	...
}
複製代碼

接下來執行 npm run dev ,webpack幫咱們啓動了一個端口號爲8080的服務器,並自動打開了瀏覽器,咱們修改代碼,能自動幫咱們打包新代碼,並刷新頁面。

總結

到這裏,一個能打包、能處理css、處理文件、自啓服務器、修改代碼後能自動打包,自動刷新頁面的配置就完成了。這樣一個簡單的配置已經實現我的寫demo的需求,例如跑跑算法代碼,測試一段代碼的輸出等等。

工具梳理

本章使用:

    • webpack、webpack-cli webpack工具庫
    • webpack-dev-server webpack web-server
  1. loader

    • file-loader 解析經過模塊化方式引入的文件,輸出成文件
    • url-loader (非必要) 經過模塊化方式引入的文件,以base64的形式輸出
    • style-loader 將css代碼以 <style> 標籤的形式嵌入 html 中
    • css-loader 解析經過模塊化引入的css文件
    • postcss-loader 提供預處理css的一些能力,擁有許多子插件,提供了許多能力
    • less-loader (非必要) 解析less代碼文件
  2. plugins

    • clean-webpack-plugin 每次打包能清空打包文件夾裏以前的內容
    • html-webpack-plugin 能自動生成Html文件,並自動引入打包生成的js文件
    • autoprefix postcss-loader的子插件,提供廠商前綴自動補全能力,如 -m-

文檔梳理

尾聲

本章節代碼倉庫代碼倉庫

本章節Github-blog: Github-blog

若是文中有錯誤/不足/須要改進/能夠優化的地方,但願能在評論裏友善提出,做者看到後會在第一時間裏處理

若是你喜歡這篇文章,👍點個贊再走吧,github的星星⭐是對做者持續創做的支持❤️️

相關文章
相關標籤/搜索