我和我的广告前端代码(六):webpack工程合并、也许我不需要gulp
隨著年初開始使用webpack重構(gòu)公司的廣告代碼,已經(jīng)有將近一年的時間了,需求也漸漸的穩(wěn)定了。我想也是時候?qū)⑦@幾個工程整理一下,順帶著處理一些歷史問題。
由于當年各個業(yè)務(wù)線沒有整合、需求也沒有固定,考慮到將來隨著不同業(yè)務(wù)線的發(fā)展方向不同,我為不同業(yè)務(wù)線的廣告代碼創(chuàng)立了不同的git工程,分別開發(fā)。但是我仍然為他們采用了相同的項目配置和基礎(chǔ)邏輯,為將來有一天需要整合的時候做準備。這就導(dǎo)致了在不同業(yè)務(wù)線的廣告代碼中我有很多相同的基礎(chǔ)模塊,一旦修改這些模塊,就要分別手動同步一遍,費時費力。因此這一次的優(yōu)化的第一要務(wù)就是合并工程。另外采用webpack開發(fā),我日后加入es6模塊后需要source-map來方便調(diào)試。最后就是進來使用vue-cli的感悟,我原有的工程太依賴gulp,在閱讀了vue-cli生成的webpack工程后,我打算嘗試將項目中的gulp替換成npm script。
因此我這次優(yōu)化的任務(wù)就有了以下的幾條:
1、工程合并:webpack多入口;
2、soucemap:加入sourcemap選項,并區(qū)分開發(fā)聯(lián)調(diào)環(huán)境和上線環(huán)境;
3、npm script替換gulp;
4、bug修改;
?
一、工程合并、多入口
最開始的時候?qū)c和wap的廣告代碼分別配置了兩個git倉庫,由于業(yè)務(wù)模式是差不多的,所以才用了相似的架構(gòu),不同點在于兩端的廣告特型是不同的、瀏覽器適配方案不同,這就導(dǎo)致了兩份代碼中有大量的相同的模塊,每次修改這些相同的模塊時要同事修改另一個,當是的做法是將這些模塊獵在一個json文件中,一旦有修改就跑一段gulp腳本同步一下。但是這樣做終究不是辦法。這本身就是一個很不合理的方案,那么我為什么要分成兩個。原因是長期以來PC的后臺和wap的后臺長期由兩個不同的后端組編寫,而且后端架構(gòu)分別由PHP和Java實現(xiàn),不同業(yè)務(wù)線的維護工作有可能拆分到別的部門來維護,這是一個歷史原因。正是基于這個原因,我沒有將兩個藕合在一起,以方有一天我需要將兩份代碼拆開交給不同的團隊來維護。
但是我仍然考慮了有一天會合并在一起,所以一直強行規(guī)范這兩個項目中邏輯結(jié)構(gòu)和相同的功能模塊保持同步,這為我能夠在未來的某一天可以順利的將兩個工程合并以及當出現(xiàn)新業(yè)務(wù)線時,可以快速編譯出一份新的廣告代碼,我的代碼一定要能支持不同的場景,并不為了某一個業(yè)務(wù)線而產(chǎn)生。事實上隨著廣告業(yè)務(wù)資源的整合與穩(wěn)定,我現(xiàn)在打算做出這種嘗試。
我在最初選用webpack也是出于多入口,理論上我只需要將wap中不同的入口模塊和業(yè)務(wù)特型拷貝到PC,然后修改webpack配置文件,就可以實現(xiàn)合并。
那么我簡單說一下webpack的多入口配置(我先給出官方文檔):
我們要關(guān)注的主要是webpack.config.js,當然你的工程中webpack配置文件可能不叫這個名字。以我的為例:
1 var path = require('path'); 2 var webpack = require('webpack'); 3 //var HtmlwebpackPlugin = require('html-webpack-plugin'); 4 //定義了一些文件夾的路徑 5 var ROOT_PATH = path.resolve(__dirname); 6 var APP_PATH = path.resolve(ROOT_PATH, './src/app'); 7 var BUILD_PATH = path.resolve(ROOT_PATH, './src/build'); 8 // var NODE_PATH = path.resolve(__dirname, 'node_modules'); 9 10 module.exports = { 11 //項目的文件夾 可以直接用文件夾名稱 默認會找index.js 也可以確定是哪個文件名字 12 entry: { 13 "yourcodepcv1": APP_PATH + '/index.js', 14 "yourcodewapv1": APP_PATH + '/index-wap.js' 15 }, 16 //輸出的文件名 合并以后的js會命名為adsfehomev1.js 17 output: { 18 path: BUILD_PATH, 19 filename: '[name].js'//, 20 // sourceMapFilename: '[file].map', 21 // devtoolLineToLine: true 22 }, 23 devtool: '#source-map', 24 externals:{ 25 jquery: "jQuery" 26 } 27 };其實,很簡單。我們一起來看一下,主要看module.exports中的entry和output,entry接收我們傳入一個對象如下圖,每一組的鍵值對都是一個入口,我這里寫了兩個入口文件。
? ? ? ? ? ? ? ? ? ? ? ?
但是webpack并不允許我們傳入一個好幾組輸出鍵值對。事實上入口中的每一個鍵值對在webpack中被視為一個“chunk”,我們在ouput中的[name]會被入口中的鍵名替換,可替換的不僅僅是鍵名,我們還可以加入[id]、[hash]、[chunkhash]等。
? ? ? ? ? ? ?
實際運行webpack后會看到終端中如下信息:
? ? ? ? ? ? ? ? ? ??
其中有一列chunks,看到我們有兩個chunk: 0和1。 0是我的pc代碼,1是wap的。而對應(yīng)的source-map也不會新建chunk。輸出是也用了我們的[name]。
實際開發(fā)中,當然不僅僅是入口不同,webpack通過require關(guān)鍵字查找文件,如果不同入口飲用了同一個模塊,但是這個模塊卻依賴pc和wap各自的模塊,我們可以在入口處定義好一個map緩存到一個通用的數(shù)據(jù)模塊,這個模塊的數(shù)據(jù)并不會硬編碼,而是由入口處傳入。也可以是各寫各的,僅僅把復(fù)用的模塊提出來飲用。但是這樣做雖然簡單但是當我想在加入一個入口時,就要寫一溜文件,并不如入口定義map這種方便,加一個文件就行。當然方法有很多,條條大路通羅馬,js語法是很強大的。
?
二、sourcemap
這個其實比較簡單,webpack是支持的,看我上面的配置文件,就可以看到 :
devtool: '#source-map'看過我第一篇文章的朋友會看到,我最開始是用requireJS寫的,好處在于開發(fā)時文件有瀏覽器異步加載,調(diào)試的時候找到那個文件就比較好調(diào)試。可是現(xiàn)在不同了我用webpack在nodeJS環(huán)境預(yù)編譯打成一個文件。試想一下文件挺大的,而且和我寫的并不是完全一樣,找個東西不太方便,何況我用ES6寫的部分更是被轉(zhuǎn)化了。我需要souce-map來告訴我應(yīng)該對應(yīng)源文件的那一行。
三、npm script代替gulp
我在開始寫的時候直接用了gulp,不得不承認gulp很強大,而且很方便。可是我要做的事情并沒有那么復(fù)雜,我需要的主要是:多任務(wù)、不用記不同的命令、webpack打包、mocha測試、jslint檢查、開發(fā)環(huán)境變異、上線環(huán)境打包、部署等。其實不需要太深厚的nodejs功力,即使不實用gulp也可以搞定。
其實我這種想法來自于我前段時間寫vue,當時我用到了vue官方的vue-cli,對 就是那個腳手架里面雖然用了webpack,可是沒有用gulp、grunt等工具。取而代替,用的是npm script。用過的同學(xué)會了解,就是package.json中那個“scripts”快捷命令。其實從另一個方面來說gulp和jQuery都是讓人又愛又恨的工具,好的是確實方便,不好的是這些工具讓我們對原生技術(shù)的原理、機制有了錯誤的理解。而且npm的包要比gulp的包要多很多,一般來說,功能都是在npm有了用著不錯,想在gulp中用才會被人封裝成gulp-XXX包。相應(yīng)的更新維護速度,誰比較快就比較明顯了。
下面我就簡單的以我的工程為例子介紹一下,如何使用npm script配置工程:
就一我dev(開發(fā)環(huán)境,watch編譯)和build(打包、壓縮)為例:npm run dev;npm run build就可以調(diào)用。
對于我來說開發(fā)環(huán)境只要在終端輸入webpack就可以了。而我原來是怎么做的:為了讓gulp能夠控制整個流程,我是在gulp中require("webpack")而是利用gulp的watch,這么做的缺點在于為了用gulp無意中讓webpack的使用更加繁瑣,而且gulp的watch相當于gulp取監(jiān)聽文件變化,在取調(diào)用webpack,如果寫的不好每次相當于從新運行webpack,ES5還好,如果用了很多l(xiāng)oader,比如ES6 bable,就會很慢(10s以上,不能算是即時編譯)。而webpack自帶的 -w不同,第一次慢一點,之后就緩存在內(nèi)存中了,即使是ES6,也會很快。
問題來了,我build為什么不想dev那樣寫?因為build不僅僅用到了webpack,而且用了不同的webpack配置。我把要做的事情封裝到minitodist.js中,并且因為build任務(wù)和cdn任務(wù)很像,我在調(diào)用npm run build的語句中傳入了一個參數(shù)‘dist’。那么有什么不同呢:
1、調(diào)取不同的webpack配置;
2、修改版本變量;
3、根據(jù)參數(shù)輸出到不同文件夾;
其實webpack配置僅僅是一部分不同,所以我用了webpack-merge來生成build用的配置:
1 var path = require('path') 2 var webpack = require('webpack'); 3 var merge = require('webpack-merge'); 4 var baseWebpackConfig = require('./webpack.config'); 5 var ROOT_PATH = path.resolve(__dirname); 6 var APP_PATH = path.resolve(ROOT_PATH, './src/app'); 7 var BUILD_PATH = path.resolve(ROOT_PATH, './dist'); 8 9 var modifiedDate = +(new Date()); 10 11 var webpackConfig = merge(baseWebpackConfig, { 12 devtool: false, 13 output: { 14 path: BUILD_PATH, 15 filename: '[name].min.js', 16 }, 17 plugins: [ 18 new webpack.optimize.UglifyJsPlugin({ 19 compress: { 20 warnings: false 21 } 22 }), 23 new webpack.BannerPlugin('This file is modified at:' + modifiedDate) 24 ] 25 }); 26 27 module.exports = webpackConfig
先寫var baseWebpackConfig = require('./webpack.config');來獲取webpack.config.js。再調(diào)用webpack-merge模塊創(chuàng)建新的配置,通過exports輸出。
比如我想要在線上環(huán)境使用已經(jīng)壓縮的代碼。我就在新的配置中的“plugins”中加入webpack.optimize.UglifyJsPlugin,并且在輸出時將文件名改成XXX.min.js(也可以不加min)。我也可以在文件頭加入有關(guān)版本的注釋(webpack.BannerPlugin)。
關(guān)于node環(huán)境調(diào)用文件的參數(shù)的問題。當你用如下語句:
node xx.js ‘a(chǎn)bc’在xx.js中可以這樣拿到:(具體原理就不解釋了)
var arguments = process.argv.splice(2); console.log(arguments[0]);如package.json文件我陸續(xù)的寫了別的任務(wù)。目前是不需要使用gulp的,對比一下我前后的依賴列表:
? ? ? 之前:之后:
是不是感覺少了很多。
總結(jié):不管部門的調(diào)整后,我是否還會維護這套廣告代碼,我仍希望交給別人一套易讀的容易維護的工程,我希望我寫的不僅僅是程序,而是工程,有始有終。
轉(zhuǎn)載于:https://www.cnblogs.com/webARM/p/6058505.html
總結(jié)
以上是生活随笔為你收集整理的我和我的广告前端代码(六):webpack工程合并、也许我不需要gulp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于oracle中to_char和to_
- 下一篇: 彻底弄懂jQuery事件原理一