我和我的廣告前端代碼(六):webpack工程合并、也許我不需要gulp

來源:互聯網
上載者:User

標籤:更新   argument   同步   build   color   注釋   處理   檔案中   基於   

  隨著年初開始使用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實現,不同業務線的維護工作有可能拆分到別的部門來維護,這是一個曆史原因。正是基於這個原因,我沒有將兩個藕合在一起,以方有一天我需要將兩份代碼拆開交給不同的團隊來維護。

  但是我仍然考慮了有一天會合并在一起,所以一直強行規範這兩個項目中邏輯結構和相同的功能模組保持同步,這為我能夠在未來的某一天可以順利的將兩個工程合并以及當出現新業務線時,可以快速編譯出一份新的廣告代碼,My Code一定要能支援不同的情境,並不為了某一個業務線而產生。事實上隨著廣告業務資源的整合與穩定,我現在打算做出這種嘗試。

  我在最初選用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.js17   output: {18     path: BUILD_PATH,19     filename: ‘[name].js‘//,20     // sourceMapFilename: ‘[file].map‘,21     // devtoolLineToLine: true22   },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: false21       }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的,對比一下我前後的依賴列表:

      之前:之後:

  是不是感覺少了很多。

  總結:不管部門的調整後,我是否還會維護這套廣告代碼,我仍希望交給別人一套易讀的容易維護的工程,我希望我寫的不僅僅是程式,而是工程,有始有終。

我和我的廣告前端代碼(六):webpack工程合并、也許我不需要gulp

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.