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