用Webpack構(gòu)建簡(jiǎn)單前端項(xiàng)目(修訂版)

這篇文章是一年前寫(xiě)的定续,當(dāng)時(shí)還用著Webpack1.x谍咆,而如今Webpack已經(jīng)是3.x版本了,如果放著不更新難免會(huì)誤人子弟私股。感謝一些網(wǎng)友的正面反饋摹察,最近總算也抽出點(diǎn)時(shí)間來(lái)更新該文章。

0. 說(shuō)點(diǎn)廢話(huà)

從文章最初發(fā)布到如今已經(jīng)整整過(guò)去一年了倡鲸,這一年里面好事沒(méi)做多少供嚎,壞事倒是做了一大堆(包括問(wèn)候一些產(chǎn)品經(jīng)理)。在這一年里我接觸過(guò)前后端分離項(xiàng)目峭状,也接觸過(guò)一些基于Ruby On Rails的全棧式項(xiàng)目克滴。然而這一年來(lái)我卻并沒(méi)有掌握多少流行的前端框架,唯一能夠確定的是

  1. 寫(xiě)頁(yè)面的時(shí)候能夠有意識(shí)地用上HTML5的標(biāo)簽优床。
  2. 熟悉基本的CSS劝赔,能夠根據(jù)設(shè)計(jì)圖,寫(xiě)出酷炫(或者不酷炫)的頁(yè)面胆敞。
  3. 對(duì)JavaScript的了解更為深入(不只是停留在Hello World的層面)着帽。
三劍客

或許我還不能算是一只合格的前端狗,我沒(méi)有熟練任何框架(如果JQuery也算的話(huà))移层,也沒(méi)有精力去折騰各種各樣的框架仍翰,我只想安安靜靜寫(xiě)樣式以及交互罷了。

1. 前言

今天的主題是Webpack观话,我似乎有點(diǎn)跑題了予借。關(guān)于如何用Webpack去搭建前端項(xiàng)目,Webpack官方文檔已經(jīng)有較為詳細(xì)的說(shuō)明匪燕,我們只需要自己著跟著文檔搭建蕾羊,掌握了套路之后便可根據(jù)自己的需求去搜索相關(guān)的插件來(lái)使用。

我這個(gè)Webpack腳手架并不是什么最佳實(shí)踐帽驯,它只是我能想到的最簡(jiǎn)單的實(shí)踐龟再,平時(shí)可以用來(lái)開(kāi)發(fā)靜態(tài)頁(yè)面。如果只是用來(lái)開(kāi)發(fā)靜態(tài)頁(yè)面那我覺(jué)得它應(yīng)該具有如下功能

  1. 簡(jiǎn)單易懂的目錄結(jié)構(gòu)尼变。
  2. 能夠自動(dòng)編譯Sass利凑,CoffeeScript等靜態(tài)資源文件。
  3. 修改HTML嫌术,CSS哀澈,JavaScript之后能夠動(dòng)態(tài)刷新頁(yè)面,不需要手動(dòng)進(jìn)行刷新度气。

下面我們逐步來(lái)實(shí)現(xiàn)這些功能割按,或者你可以直接從Github(這個(gè)不是master分支)上獲取相關(guān)代碼。

2. Webpack構(gòu)建簡(jiǎn)單的前端腳手架

從零開(kāi)始搭建Webpack服務(wù)沒(méi)有比官方文檔更詳細(xì)的了磷籍,我這里就順著文檔簡(jiǎn)單講講構(gòu)建流程适荣。

1) 初始化項(xiàng)目现柠,安裝Webpack

mkdir static-page && cd static-page  # 創(chuàng)建并移動(dòng)到項(xiàng)目目錄
npm init -y  # 生成項(xiàng)目信息,并把信息存放到 package.json文件中
npm install --save-dev webpack # 安裝webpack弛矛,由于只在開(kāi)發(fā)環(huán)境下會(huì)用到够吩,這里用了`--save-dev`標(biāo)識(shí)

完成之后我們目錄下會(huì)有這些文件

> ls
node_modules package.json
  1. node_modules 用來(lái)存放我們通過(guò)npm命令安裝的軟件。
  2. package.json 文件記錄該項(xiàng)目的元信息丈氓,以及一些依賴(lài)包信息周循。

2) 創(chuàng)建頁(yè)面文件,以及js入口文件

創(chuàng)建一個(gè)index.html文件用于存放我們的頁(yè)面內(nèi)容万俗,我把它放在dist/目錄里面湾笛,以及一個(gè)名為index.js的webpack入口文件,我把它放在src/目錄下面该编。

目錄結(jié)構(gòu)大概如下

├── dist
│   └── index.html
├── node_modules
├── package.json
└── src
    └── index.js

PS: 所謂入口文件就是從這個(gè)文件中引入的資源都會(huì)被Webpack統(tǒng)一打包處理迄本,無(wú)論它是圖片資源,樣式資源课竣,還是JS資源嘉赎。Webpack會(huì)根據(jù)配置對(duì)不同類(lèi)型的資源文件進(jìn)行不同方式的處理。

<!-- dist/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <h1>Ruby</h1>
  </body>
</html>
// src/index.js
document.body.style.background = 'red'

簡(jiǎn)單起見(jiàn),這里的js只做了改變背景色的操作。大家都能看出來(lái)坷牛,目前兩個(gè)文件是還沒(méi)有關(guān)聯(lián)的肉盹,接下來(lái)我想辦法讓他們關(guān)聯(lián)起來(lái)看峻。這個(gè)時(shí)候就需要先配置Webpack,這里我采用了官方的配置。文件放在根目錄下的 webpack.config.js文件中

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

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

配置文件都用js來(lái)寫(xiě)。寫(xiě)過(guò)js的人應(yīng)該很容易就可以理解关霸,它所代表的任務(wù)是解析入口文件./src/index.js然后對(duì)資源進(jìn)行處理,最后把處理好的資源統(tǒng)一輸出到./dist/bundle.js文件中杰扫。

配置好之后運(yùn)行命令

> ./node_modules/webpack/bin/webpack.js # 運(yùn)行我們一開(kāi)始安裝的Webpack

Hash: 15871b00d29beee17361
Version: webpack 3.8.1
Time: 63ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.51 kB       0  [emitted]  main
   [0] ./src/index.js 33 bytes {0} [built]

它會(huì)自動(dòng)尋找當(dāng)前目錄下的webpack.config.js配置文件队寇,然后編譯并打包相應(yīng)的文件,現(xiàn)在我們的目錄結(jié)構(gòu)大概會(huì)是這樣了

.
├── dist
│   ├── bundle.js
│   └── index.html
├── node_modules
├── package.json
├── src
│   └── index.js
└── webpack.config.js

期望的出口文件已經(jīng)生成章姓,接下來(lái)只需要在html里面引入這個(gè)入口文件便可佳遣, 加上一行<script src="bundle.js"></script>

<html>
  ...
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

直接在瀏覽器打開(kāi)index.html頁(yè)面就能看到如下效果。

直接瀏覽器顯示

這樣第一點(diǎn)就已經(jīng)完成了凡伊,它有良好的目錄結(jié)構(gòu)零渐,不過(guò)現(xiàn)在看來(lái)這種簡(jiǎn)單的目錄結(jié)構(gòu)我們自己也懂得怎么構(gòu)建,用Webpack的必要性似乎不大系忙。接下來(lái)我們看看如何用Webpack方便地管理Sass等靜態(tài)資源诵盼。

3) 編譯并打包Sass文件

現(xiàn)代的前端領(lǐng)域,為了方便樣式文件的管理與開(kāi)發(fā),我們一般會(huì)在項(xiàng)目引入Sass拦耐,或者Less這些技術(shù)耕腾,然而,瀏覽器卻無(wú)法直接解析這類(lèi)型的樣式文件杀糯,也就是說(shuō)如果要用到生產(chǎn)環(huán)境中,我們必須把這些資源進(jìn)行預(yù)編譯苍苞。

那么Webpack如何管理Sass資源呢固翰?很簡(jiǎn)單,我們只需要在入口文件src/index.js里面引入Sass的文件便可羹呵。我們首先創(chuàng)建一個(gè)src/example.scss的文件骂际,并像下面這般引入。

// src/example.scss /
body {
    h1 {
        color: #fff;
        font-size: 40px;
        font-family: fantasy;
    }
}
// src/example.scss
import './example.scss';

document.body.style.background = 'red'

接下來(lái)在根目錄下運(yùn)行webpack的命令

./node_modules/webpack/bin/webpack.js

發(fā)現(xiàn)會(huì)有報(bào)錯(cuò)信息

ERROR in ./src/example.scss
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type.
| body {
|     h1 {
|         color: #fff;
 @ ./src/index.js 1:0-24

Webpack還是非常人性化的冈欢,它告訴我們?nèi)鄙倭撕线m的Loader用來(lái)加載對(duì)應(yīng)的Sass文件歉铝,如果沒(méi)有對(duì)應(yīng)的加載器則無(wú)法加載對(duì)應(yīng)的資源文件。而Webpack對(duì)應(yīng)的Sass加載器在這里凑耻。

只需要按照文檔的說(shuō)法太示,安裝缺少的加載器與編譯工具便可

npm install style-loader sass-loader node-sass css-loader --save-dev

具體每一個(gè)包有什么作用,文檔會(huì)提到香浩,這里不詳細(xì)說(shuō)类缤。接下來(lái)只需要把加載器的配置放到webpack.config.js文件里面便可。

// webpack.config.js
module.exports = {
    ...
    module: {
        rules: [{
            test: /\.scss$/,
            use: [{
                loader: "style-loader" // creates style nodes from JS strings
            }, {
                loader: "css-loader" // translates CSS into CommonJS
            }, {
                loader: "sass-loader" // compiles Sass to CSS
            }]
        }]
    }
};

然后再次運(yùn)行Webpack的命令邻吭, 便可以編譯通過(guò)了餐弱。

如果我們不想要每次修改資源都運(yùn)行一次Webpack的命令,而是想讓W(xué)ebpack監(jiān)控我們的文件改動(dòng)囱晴,并自動(dòng)打包膏蚓,我們可以在命令后面加上--watch標(biāo)識(shí)

> ./node_modules/webpack/bin/webpack.js --watch

Webpack is watching the files…

Hash: 691c616891a1a6c230b3
Version: webpack 3.8.1
Time: 698ms
    Asset     Size  Chunks             Chunk Names
bundle.js  19.1 kB       0  [emitted]  main
   [0] ./src/index.js 65 bytes {0} [built]
   [1] ./src/example.scss 1.15 kB {0} [built]
   [2] ./node_modules/css-loader!./node_modules/sass-loader/lib/loader.js!./src/example.scss 237 bytes {0} [built]
    + 3 hidden modules

這樣每次我們改動(dòng)資源文件,Webpack就會(huì)自動(dòng)重新編譯打包畸写,我們只管刷新頁(yè)面便可驮瞧。下面是我把字體顏色改成綠色之后直接刷新頁(yè)面的結(jié)果。

修改文件后直接刷新頁(yè)面

由于我們的Webpack服務(wù)開(kāi)啟了--watch模式艺糜,我們不需要再次手動(dòng)去運(yùn)行Webpack命令重新打包資源剧董。

4) 頁(yè)面自動(dòng)刷新

如果每次改了樣式文件之后還要手動(dòng)刷新的話(huà),還是有點(diǎn)麻煩破停,效率還不夠高翅楼。有沒(méi)有辦法修改前端文件之后自動(dòng)刷新頁(yè)面?這個(gè)時(shí)候請(qǐng)出神器webpack-dev-server.

npm install --save-dev webpack-dev-server

簡(jiǎn)單配置一下webpack.config.js文件真慢,加上下面配置

module.exports = {

    .....
    devServer: {
        contentBase: './dist'
    },
};

接下來(lái)運(yùn)行命令

./node_modules/webpack-dev-server/bin/webpack-dev-server.js
Project is running at http://localhost:8081/
webpack output is served from /

便可啟動(dòng)服務(wù)毅臊,我們只需要在瀏覽器訪問(wèn)http://localhost:8081/這個(gè)地址便可。

此時(shí)簡(jiǎn)單改變一下我們的js文件的內(nèi)容黑界,改變背景色

import './example.scss';

document.body.style.background = 'blue'

我們不再需要手動(dòng)刷新頁(yè)面了管嬉,webpack會(huì)自動(dòng)被重新打包皂林,并使得頁(yè)面自動(dòng)刷新。

修改靜態(tài)資源自動(dòng)刷新

但這里有一個(gè)問(wèn)題蚯撩,如果我們?nèi)バ薷臎](méi)有被入口文件托管的文件础倍,比如index.html文件,就算我們修改html文件的內(nèi)容胎挎,頁(yè)面也不會(huì)自動(dòng)更新沟启。

改HTML手動(dòng)刷新

可見(jiàn)修改index.html文件后需要要手動(dòng)刷新才行,要怎么使得當(dāng)HTML文件被修改后自動(dòng)刷新頁(yè)面呢犹菇?很簡(jiǎn)單

修改webpack.config.js配置文件德迹,在devServer上面加上watchContentBase: true這個(gè)配置便可。

.....
module.exports = {
    ....
    devServer: {
      contentBase: './dist',
      watchContentBase: true
    },
    ....
};

結(jié)果如下

自動(dòng)刷新

可見(jiàn)揭芍,當(dāng)我們修改index.html文件的時(shí)候網(wǎng)頁(yè)會(huì)自動(dòng)刷新胳搞。

5) 還有點(diǎn)小問(wèn)題

這個(gè)問(wèn)題是我后來(lái)才發(fā)現(xiàn)的,我們?cè)谕ㄟ^(guò)webpack命令生成了一個(gè)叫bundle.js的文件称杨,但是很奇怪的是肌毅,當(dāng)我們刪除了這個(gè)文件之后運(yùn)行webpack-dev-server這個(gè)服務(wù)的話(huà),它并不會(huì)重新生成這個(gè)文件列另。

> ls dist/
index.html

上面是我刪除了dist/bundle.js并運(yùn)行webpack-dev-server之后的結(jié)果芽腾,dist/目錄下并不會(huì)重新生成bundle.js文件。但是我們的服務(wù)并不會(huì)提示我們說(shuō)找不到bundle.js這個(gè)文件页衙。我們的一切服務(wù)依然正常運(yùn)行摊滔。

頁(yè)面依然能夠刷出來(lái)

這是因?yàn)?strong>webpack-dev-server會(huì)把打包好的數(shù)據(jù)存在內(nèi)存中,并不會(huì)做文件IO操作店乐,所以我們看不到對(duì)應(yīng)文件的生成艰躺。

因此,如果我們使用webpack-dev-server來(lái)輔助開(kāi)發(fā)的話(huà)其實(shí)是不會(huì)生成對(duì)應(yīng)出口文件的眨八,從內(nèi)存中加載數(shù)據(jù)往往效率更高腺兴。

3. 尾聲

有經(jīng)驗(yàn)的webpack使用者來(lái)說(shuō)或許不屑于像我這樣做,況且如今不同的框架官方都對(duì)webpack配置進(jìn)行了深度定制廉侧。在項(xiàng)目初始化的時(shí)候我們大可以站在巨人的肩膀上直接構(gòu)建項(xiàng)目腳手架页响。使用如create-react-appvue-cli等腳手架工具來(lái)初始化我們的項(xiàng)目段誊。大家可以根據(jù)自己的技術(shù)棧來(lái)選擇合適的工具闰蚕。

前端技術(shù)著實(shí)讓人眼花繚亂,技術(shù)本身也參差不齊连舍,各種技術(shù)都有他們的優(yōu)缺點(diǎn)没陡,我以為能夠結(jié)合場(chǎng)景解決實(shí)際問(wèn)題的方案才能算是最佳實(shí)踐,我不排斥折騰,但我并不推薦瞎折騰盼玄。當(dāng)如今前端技術(shù)讓你難以選擇贴彼,并感到焦慮的時(shí)候,我建議可以先考慮從基礎(chǔ)入手埃儿,就是下面這三位

HTML + CSS + JavaScript

流行前后端分離的今天我們就一定要把我們的項(xiàng)目前后端分離嗎器仗?流行使用Vue,React這些框架的今天我們就必須拋棄JQuery嗎蝌箍?個(gè)人不敢茍同青灼,前后端分離的項(xiàng)目固然有它的優(yōu)勢(shì)。如果你正在使用前后端分離的方式去構(gòu)建一個(gè)簡(jiǎn)單的博客系統(tǒng)妓盲,或許你該靜下心來(lái)想想,這種選擇是否只是在增加開(kāi)發(fā)難度专普?

當(dāng)你手上有錘子的時(shí)候悯衬,看什么都像釘子。

很感謝看到這里檀夹。

Happy Coding and Writing !!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筋粗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子炸渡,更是在濱河造成了極大的恐慌娜亿,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚌堵,死亡現(xiàn)場(chǎng)離奇詭異买决,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吼畏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)督赤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人泻蚊,你說(shuō)我怎么就攤上這事躲舌。” “怎么了性雄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵没卸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我秒旋,道長(zhǎng)约计,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任滩褥,我火速辦了婚禮病蛉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己铺然,他們只是感情好俗孝,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著魄健,像睡著了一般赋铝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沽瘦,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天革骨,我揣著相機(jī)與錄音,去河邊找鬼析恋。 笑死良哲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的助隧。 我是一名探鬼主播筑凫,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼并村!你這毒婦竟也來(lái)了巍实?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哩牍,失蹤者是張志新(化名)和其女友劉穎棚潦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體膝昆,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丸边,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了外潜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片原环。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖处窥,靈堂內(nèi)的尸體忽然破棺而出嘱吗,到底是詐尸還是另有隱情,我是刑警寧澤滔驾,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布谒麦,位于F島的核電站,受9級(jí)特大地震影響哆致,放射性物質(zhì)發(fā)生泄漏绕德。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一摊阀、第九天 我趴在偏房一處隱蔽的房頂上張望耻蛇。 院中可真熱鬧踪蹬,春花似錦、人聲如沸臣咖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夺蛇。三九已至疚漆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刁赦,已是汗流浹背娶聘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甚脉,地道東北人丸升。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像牺氨,于是被迫代替她去往敵國(guó)和親发钝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350