Webpack自動化工程

近幾年,前端各種框架工具層出不窮,從兩三年前還是一個jQuery搞定全站,到之后 requirejs/seajs,node,gulp/webpack,Angular/React/Vue,RN/weex的不斷涌現(xiàn),完全顛覆了原來的前端開發(fā)模式。

那么這些框架和工具給我們到底帶來了什么好處呢?其實我認為最核心莫過于這兩點:模塊化開發(fā)、自動化工程。而本次前端重構所圍繞的核心問題就是自動化工程,將原有的 gulp版本的項目利用webpack徹底改造,順利消滅了既繁瑣又易錯的人工操作。

gulp 版本的痛點

我們先來看下奇貨商城之前的開發(fā)流程:

從上圖可以看出,我們奇貨前端開發(fā)之前存在的一些痛點:

  1. 前端在后端項目里面修改 vm文件聯(lián)調(diào);

  2. 開發(fā)聯(lián)調(diào)需要上傳靜態(tài)資源到測試域名 CDN

  3. 不同目錄下的資源還需要在 CDN上傳網(wǎng)站上一級一級目錄的點開再上傳;

  4. 上線前需要人工去替換 vm 文件里的 CDN路徑;

  5. 上線前還需要人工去上傳靜態(tài)資源到正式域名 CDN

  6. 開發(fā)模式不支持 es6 轉(zhuǎn)義,導致低端安卓機無法在本地進行前端調(diào)試;

  7. gulp-babel不完全支持es6轉(zhuǎn)es5,導致部分低端安卓機出現(xiàn)各種莫名其妙的問題;

以上這些痛點,造成的重復性無用功,既浪費精力又著實讓人蛋疼,而經(jīng)過這次的框架重構,只需一鍵操作,就可完成聯(lián)調(diào)和發(fā)布的部署。省心省力還不會出錯。

如何利用 webpack 做自動化

先看一下改版后,奇貨商城的開發(fā)流程:


從上圖可以看到,我們經(jīng)過改版后做到了:

  1. **vm **文件自動生成

  2. 開發(fā)聯(lián)調(diào)直接讀取本地靜態(tài)資源

  3. 打包后所有資源在同一級目錄,一次性拖拽上傳(下個版本將實現(xiàn)前靜態(tài)資源自動上傳)

  4. 只需一行配置項,自動生成對應的線上 **CDN **路徑

  5. 完美的 babel-loader,**es6 **語法也可在低端安卓機上輕松本地調(diào)試;

下面我們看看如何實現(xiàn)。

項目結構

下面是部分主要目錄結構:

├── build   (所有的webpack配置項)
│   ├── build.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js    (★入口配置,生成文件配置,vm生成都靠這個文件)
│   ├── webpack.base.conf.js    (基礎配置)
│   ├── webpack.dev.conf.js     (開發(fā)模式配置)
│   └── webpack.prod.conf.js    (生成環(huán)境配置)
├── config  (node環(huán)境變量,入口文件的配置)
│   ├── dev.env.js
│   ├── entry.js    (頁面文件列表)
│   ├── index.js    (★主配置文件)
│   ├── prod.env.js
│   └── skinEntry.js    (皮膚文件列表)
├── dist    (打包后生成的文件夾,已全部轉(zhuǎn)成vm)
│   ├── goods
│   │   ├── detail.vm
│   ├── index.vm
│   └── static  (打包后-靜態(tài)資源文件)
│       ├── css
│       ├── js
│       └── skins   (打包后皮膚文件夾)
│           ├── default
│           │   ├── default.1184b4d7.js
│           │   ├── default.f07ae9df.css
│           │   └── default.html
│           ├── huotu
│           └── pay
├── mock
├── package.json
├── routes
├── src (源文件)
│   ├── js
│   │   ├── components
│   │   ├── goods
│   │   │   ├── detail.js
│   │   │   └── skins
│   │   │       ├── default.js
│   │   │       ├── huotu.js
│   │   ├── index.js
│   ├── less
│   │   ├── components
│   │   ├── goods
│   │   │   ├── detail.less
│   │   │   └── skins
│   │   │       ├── default.less
│   │   │       ├── huotu.less
│       ├── index.less
│   └── pages
│       ├── components
│       ├── goods
│       │   ├── detail.html
│       │   └── skins
│       │       ├── default.html
│       │       ├── huotu.html
│       └── index.html
├── static
│   └── images
└── unit    (公共庫)
    ├── common  (業(yè)務組件)
    │   ├── js
    │   └── less
    ├── layout  (公共頁面)
    │   ├── footer.html
    │   └── header.html
    └── lib     (第三方組件)

以上是我們奇商城的前端目錄結構。

webpack的一些必用的loaderplugin,

例如

less-loader, style-loader, file-loader, html-loader, 還有UglifyJsPlugin, ExtractTextPlugin, OptimizeCSSPlugin

等等,在這里就不詳細展開了。

我們重點說說以下幾點核心:

node 腳本調(diào)用 webpack

通過node腳本來調(diào)用webpack,而不是直接在命令行啟動webpack,會有這么幾個用處:

  • 通過nodeexpress做本地mock數(shù)據(jù);

  • 開發(fā)環(huán)境和生產(chǎn)環(huán)境的公共配置項,通過webpack-merge模塊做抽離,方便維護;

  • 可以設置node環(huán)境變量,以區(qū)分不同環(huán)境中的打包配置,這點在后面還有一個大招;這貨可以說是整個構建過程里,核心中的核心了。

自動生成 vm、開發(fā)環(huán)境調(diào)用本地資源,以及皮膚文件的管理都有這個插件的功。部分代碼:

new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'production' ? path + name + '.vm' : path + name + '.html',
  template: template,
  inject: false,
  chunks: [pathBuild + name, 'vendor', 'manifest']
})

通過判斷node環(huán)境變量,決定生成vm還是本地html;通過這個插件實現(xiàn)了 js 模塊打包,公共模塊提取,客戶端緩存&增量發(fā)布,皮膚文件生成。部分代碼:

for (let i = 0; i < entry.length; i++) {
  let item = entry[i]
  let path = item.path
  let name = item.name
  let pathBuild = path.replace(/\//g, '-');
  result[pathBuild + name] = './src/js/' + path + name + '.js'
}

for (let i = 0; i < skinEntry.length; i++) {
  let item = skinEntry[i]
  let path = item.path
  let name = item.name
  if (process.env.NODE_ENV === 'production') {
    result['../skins/' + path + name] = './src/js/goods/skins/' + name + '.js'
  } else {
    result['skins/' + path + name] = './src/js/goods/skins/' + name + '.js'
  }
}

Object.assign(result, {
  vendor: ['@unit/common/js/base', '@unit/common/js/util']
})

// 公共文件提取
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor', // 注意不要.js后綴
  chunks: utils.computeChunks(entryConfig, '')
})

// 避免修改業(yè)務代碼導致vendor的md5改變,保留文件緩存
new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
})

自動化部署

自動化部署是在打包服務器通過腳本實現(xiàn)的,先通過npm命令打包前端工程,然后將代碼copy到后端工程中,最后打包后端項目,再發(fā)布。

遇到的困難

公共文件的引入

webpack官方文檔并沒有如何引入公共html文件的說明,這一點是在翻了
N多資料后才發(fā)現(xiàn)的,最終的方案是:
去掉 webpack.config.js 文件中配置的全局html-loader,這樣html模版文件就不會被html-loader解析,我們可以使用ejs 語法嵌入其他 html 頁面和圖片資源。因為沒了全局的html-loader解析html文件,使用ejs語法嵌入的資源返回的是 ejs 代碼,還需要使用html-loader來解析成html代碼。

html-loader!)表示引用html-loader這個加載器來解析

<%= require('html-loader!../layout/header.html') %>

但是這樣將全局html-loader去掉后,又碰到了下面的問題。

jsp 變量的引入

vm中有時需要直接引用后端的變量,如${cssUrl},就像這樣:

這時候webpack打包居然就報錯了,報錯了:

原因排查

出現(xiàn)這個問題的原因應該是由于HtmlWebpackPlugin這個插件引用的模版默認是 ejs,當不使用全局html-loader的時候,模板文件其實是以 ejs 解析的,而${cssUrl}ejs 中也識別為一個變量,當然就報錯了。

解決方法

這過程中,整個周末都在想這個問題,甚至已經(jīng)開始考慮用gulp+webpack的方案了。。又翻了很多資料,突然想到既然是ejs模板,可以嘗試了一些 ejs 去寫,而不是非要把這個模板以html的方式 loader 進來,然后就有了如下方法:

<link href="<%= '${cssUrl}' %>" rel="stylesheet">

這時候就被識別為一個字符串了!成功解決。

進一步探索,巧用 node 環(huán)境變量
上面的方法解決的其實也是挺丑的,因為本地開發(fā)的時候需要引用本地文件的,上線的時候又得傻乎乎地去一個個地方去替換:

<!-- <link href="<%= skinCss %>" rel="stylesheet">   -->
<link href="/skins/pay/pay.css" rel="stylesheet">

然后馬上試了下,在模板文件中用 ejs 去讀node 環(huán)境變量
process.env.NODE_ENV,果然能取到值,就有了下面這個相對完美的方案:

<% 
if (process.env.NODE_ENV === 'production') { 
  skinCss = '${cssUrl}';
} else { 
  skinCss = '/skins/pay/pay.css'; 
} 
%>

<link href="<%= skinCss %>" rel="stylesheet">

其中production就是利用 **node **啟動 **webpack **時配置的,在這里派上了大用場。

End

到這里,我們奇貨商城已經(jīng)實現(xiàn)了前端工程自動化,再也不用一遍又一遍地去 vm 里修改路徑,人工去記著改了哪些文件,要上傳哪些靜態(tài)資源。更加不用擔心漏傳什么資源文件而導致線上bug辣。

作者:Woodk
出處:http://www.cnblogs.com/woodk/p/7459467.html

技術交流QQ群 :238757010

關注微信公眾號Reboot51后臺回復 python、自動化即可獲得相應課程的試聽資料


運維自動化班 6 期報名開始

12月17日(周日)

課程大綱 http://51reboot.com/course/devops

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • GitChat技術雜談 前言 本文較長,為了節(jié)省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,894評論 7 110
  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,371評論 7 35
  • 在現(xiàn)在的前端開發(fā)中,前后端分離、模塊化開發(fā)、版本控制、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,659評論 1 32
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,445評論 4 31
  • ?今年3月,商務部就美國鋁箔生產(chǎn)商提出的申訴,對中國制造商涉嫌在美國市場傾銷展開調(diào)查,并于8月初初步裁定對從中國進...
    貿(mào)立方閱讀 171評論 0 0

友情鏈接更多精彩內(nèi)容