摘要:概述從去年短時間內對現有系統的改造到如今穩定實施,已經好幾個月,這套流程滿足了日常前端開發的流程。在講這之前簡單說下前端模塊化歷程。模塊化以上是在規范出來之前的編碼方式,大家應該非常熟悉。只要在代碼中用來異步加載模塊即可。
概述
從去年短時間內對現有系統的改造到如今穩定實施,已經好幾個月,這套流程滿足了日常前端開發的流程。由于之前項目組的模塊化本身做的不是很好,基本算是推到一半重來,雖然陣痛,但回顧起來確實非常值得。webpack,簡單來說就是前端靜態資源的打包工具,確實好用,原理也很簡單,比以AMD、CMD為標準的模塊加載器好用多了,難怪玉伯說要給seajs、requirejs立一塊墓碑了。在講webpack這之前簡單說下前端模塊化歷程。
模塊化1.0// a.js (function(){ // todo a })(); // b.js (function(){ // todo b })(); // index.html
以上是在CommonJS規范出來之前的編碼方式,大家應該非常熟悉。另外還有通過命名空間的方式來進行模塊化,其實也沒有真正的解決問題。
模塊化2.0// a.js define(function(require, exports, module){ // todo a }) // b.js define(function(require, exports, module){ var a = require("./a"); // todo b }) // index.html
這就是過去幾年大家都非常熟悉的模塊化方式,在發布上線時通過構建工具,提取模塊id、以及模塊的依賴,合并壓縮代碼等等構建工作。
但是用requirejs或者seajs,還是有些問題:
只能模塊化加載js、css,而且還不幫你合并,需要自己寫插件去做合并的邏輯,組件化并不簡單。
異步加載也不好用,尤其是部署時,hash后的資源路徑自動替換還比較麻煩。
程序還是要依賴seajs這個幾kb的庫,總感覺有點多余。
模塊化3.0webpack出來后,優雅的解決了很多問題,并且簡單好用。它能把各種資源,例如JS(含JSX)、coffee、樣式(含less/sass)、html、圖片等靜態資源都作為模塊來處理。同時擁有異步加載的能力,非常適用于大型復雜的webapp的場景。webpack有以下特點:
兼容AMD/CMD的模塊加載
js模塊的寫法遵循CommonJS規范
模塊化所有靜態資源(JS、CSS、html、圖片、字體等)
開發、部署便捷,能替代大部分 grunt/gulp 的工作,比如打包、壓縮混淆、圖片轉base64等
通過一個簡單的配置文件即可搞定這些。
實戰結合項目本身的特點,部分功能webpack無法做到,最終選用gulp+webpack方式來支撐前端的工作流,項目需求:
最小化配置項(webpack.config.js)
所有資源使用增量發布策略,文件名全部 md5 版本化
支持多種模塊化策略,使用 webpack 進行模塊化打包
自動替換 html/js 內部資源引用路徑,替換為 cdn/md5 版本化路徑
輕松支持 js資源內嵌到頁面
開發時監聽文件,自動上傳到開發機
由于css是由重構同學寫,雪碧圖,壓縮、發布等等都由他們來做,所以沒有考慮加入到構建流程中來。
項目目錄結構如下:
src/ js/ widget/ css/ img/ project_tpl/ gulpfile.js app/ js/ css/ img/ index.html tpl/ webpack.config.js gulpfile.js app/
src目錄下是項目的源代碼,每個目錄(app)即為一個項目,為了盡量避免沖突,一個人開發并維護一個項目下的代碼。
project_tpl為項目的模板,通過gulp新建項目,完成一些初始化配置,初始化后基本無需配置即可進行項目開發。
js/css/img為站點的一些公共資源模塊,widget為公共基礎組件。
app項目下為業務的css、js、tpl目錄,tpl為前端模板目錄,可以通過webpack的html-loader插件加載。
gulpfile.js、webpack.config.js 為項目的構建工具配置文件。
這樣一個項目的腳手架搭建完成,可以開始為項目添磚加瓦了。可以點擊這里看github上的例子。
webpack配置文件var webpack = require("webpack"); var globalConfig = require("../global.config"); var commonJSEntry = globalConfig.jsCommon; var path = require("path"); module.exports = { // 如果項目有多個HTML,或者多個入口 // 配置js入口文件,base是公共庫配置,除了打包工具自動化抽取共用的模塊,也可以自定義配置哪些模塊為共用的。 entry:{ index: "./js/index", base: commonJSEntry, }, // 文件產出目錄 output:{ filename:"../test/js/[name].js", // 異步加載的chunk,命名規則,chunk我暫時理解為從合并的代碼里分離出來的代碼塊,在處理非首屏邏輯,或者異步加載邏輯可以用這個。只要在js代碼中用require.ensure來異步加載模塊即可。 chunkFilename: "../test/js/[chunkhash:8]_chunk.js", // 資源文件的CDN前綴 publicPath: debug ? "" : "http://cdn.xxx.com/webpack/test/" }, resolve: { // 模塊的別名,通常可以為第三方模塊 alias: { ajax: "../../js/base/ajax", dom: "../../js/base/dom" }, // root模塊的根路徑,可以指定從哪里找模塊,可以為數組[] // 這樣在模塊依賴的時候就不要寫require(../../../xx.js) // 直接為require(xx) root: path.resolve("../../js") }, // 模塊加載器,加載不同類型的文件,需要下載或者開發loader插件,以下為加載html模塊的加載器 loader: [ {test: /.html$/, loader: "html"} ], /* 1、可以通過配置文件指定哪位模塊為公共模塊,這樣功能模塊可以長期緩存。 解釋下這個插件的意思,就是提取公共的chunk,base對應了entry中的配置,"../test/js/common.js"是產出的路徑,也就是將commonJSEntry中的配置模塊合并成一個common.js文件。 2、webpack也可自動提取頁面之間公用的代碼作為公共部分。下面的代碼即是自動提取公共代碼了。 var commonsPlugin = new webpack.optimize.CommonsChunkPlugin("../test/js/common.js"); */ plugins: [ new webpack.optimize.CommonsChunkPlugin("base", "../test/js/common.js") ] };
由于項目的特性,沒有用到熱插拔,所以就不進行講解了。
gulp跑起來webpack最終是當做gulp的一個插件來運行,讀取的上述的webpack配置文件。
gulp.task("watch-html", function() { // upload }); gulp.task("watch-module", function() { var watchPath = [ "../js/**", "../css/**", "../widget/**", "js/**", "css/**", "tpl/**" ]; gulp.watch(watchPath, function(event){ gulp.src(watchPath) .pipe(webpack(require("webpack.config"))) .pipe(gulp.dest(releaseRelativePath + projectName)) .pipe(upload(opt, function(err, data){}) }) }); gulp.task("default", ["watch-html", "watch-module"]); // release build webpack module gulp.task("release-module", function() { var releasePath = [ "../js/**", "../css/**", "../widget/**", "js/**", "css/**", "tpl/**" ]; return gulp.src(watchPath) .pipe(webpack(require("webpack.config"))) .pipe(uglify()) .pipe(hash()) .pipe(rename(function(path) { // 獲取當前的日期,將發布文件已日期歸類,更方便查找文件 path.dirname = path.dirname + "/" + year + month + day; }) .pipe(gulp.dest(releaseRelativePath + projectName)) .pipe(upload(opt, function(err, data){}) }) }); // release build html gulp.task("release", ["release-module"], function(){ gulp.src(["**/*.html"]) .pipe(parseHtml(releaseRelativePath + projectName, CDN_URL)) .pipe(gulp.dest(releaseRelativePath + projectName)) .pipe(upload(opt, function(err, data){}) .pipe(uploadToCDN()) })
(以上用到的部分npm模塊是自定義的)。
1、項目開始前,通過gulp init -p YourProjectName 來初始化項目
2、開發和發布兩套命令,開發:gulp,發布:gulp release
3、需要自行編寫gulp插件來替換html中引用資源的路徑,原理也很簡單,在構建webpack模塊后,將產出的文件列表與原文件的映射關系保存在數組,查找html中引用的js路徑,替換成hash后就可以了。
通過以上方法,就可以滿足我們項目之前的需求,基本上做到自動化,自動構建,自動發布腳本,html文件走內部發布系統發布。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79464.html
摘要:前言與是目前圈子內比較活躍的前端構建工具。對于初學者來說,對這二者往往容易認識不清,今天,就從事件的源頭,說清楚與。它可以將許多松散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。打包后形成的文件出口。 前言:Webpack 與 gulp是目前圈子內比較活躍的前端構建工具。網上有很多二者比較的文章,面試中也會經常遇到gulp,Webpack的區別這樣的問題。對于初學者來說,對這二...
摘要:所以它在某些程度上,跟的功能有些相同。嚴格上講,模塊化不是他強調的東西,他旨在規范前端開發流程。更是明顯強調模塊化開發,而那些文件壓縮合并預處理等功能,不過是他附帶的功能。 1. webpack 是什么? showImg(https://segmentfault.com/img/remote/1460000012293461); 先來說一下 webpack 是什么。 webpack 的...
摘要:主有前端后端,并加,各一名。本著工欲善其事,必先利其器的理念,一直以來在工作效率這塊,略懷執念一個問題不應該被解決兩次。下圖為開發項目機制所涉及到的插件工欲善其事,必先利其器,語言,框架皆可以歸結為器而不當僅局限于開發工具以及機。 原文鏈接: http://www.jeffjade.com/2016/05/08/106-vue-es6-jade-scss-webpack-gulp/ 一...
摘要:那時候所配置的任務監聽匹配文件的變化自動刷新瀏覽器自動編譯自動補全前綴多雪碧圖合并拼圖等等基于編譯圖片的任務,已經是完全滿足我們的需求了。直至到后來在雪碧圖的合并,多倍圖的輸出上,在上苦苦找尋不了比較完美的解決方案等等。 折騰 從 2015 到現在,短短的三年內,幾乎每年折騰一下工作流的 更新換代 。從最早開始使用 Grunt 到 Gulp 再到 Webpack,再到 Rollup,...
閱讀 515·2021-10-09 09:44
閱讀 2084·2021-09-02 15:41
閱讀 3555·2019-08-30 15:53
閱讀 1833·2019-08-30 15:44
閱讀 1290·2019-08-30 13:10
閱讀 1196·2019-08-30 11:25
閱讀 1461·2019-08-30 10:51
閱讀 3367·2019-08-30 10:49