前端工程化——構(gòu)建工具選型

注:文章源于2017年8月的一次內(nèi)部分享,部分?jǐn)?shù)據(jù)可能已經(jīng)過時。

一、什么是前端工程化

前端工程化是依據(jù)業(yè)務(wù)特點,將前端開發(fā)的規(guī)范、流程、技術(shù)、工具、經(jīng)驗等形成規(guī)范并建立成一種標(biāo)準(zhǔn)的體系。

二、為什么要前端工程化

實現(xiàn)前端工程化的目的簡單來說就是通過流程規(guī)范、自動化工具來提升前端的開發(fā)效率、性能、質(zhì)量、多人協(xié)作能力以及開發(fā)體驗。

近幾年前端仍保持較高的速度發(fā)展,前端開發(fā)面臨著的流程、資源組織和協(xié)同開發(fā)等各方面的挑戰(zhàn),所以建立前端工程化是各個團(tuán)隊必經(jīng)的成長過程。

但由于每個公司、每個團(tuán)隊甚至每個項目都有自己的特點,所以這里先暫時拋開規(guī)范、流程、技術(shù)這些主觀的東西,從工具入手,聊聊工具的特性及適應(yīng)場景,從而找到最適合自己團(tuán)隊項目的工程化方案。

三、構(gòu)建工具

構(gòu)建工具的主要功能就是實現(xiàn)自動化處理,例如對代碼進(jìn)行檢查、預(yù)編譯、合并、壓縮;生成雪碧圖、sourceMap、版本管理;運(yùn)行單元測試、監(jiān)控等,當(dāng)然有的工具還提供模塊化、組件化的開發(fā)流程功能。

網(wǎng)上各類的構(gòu)建工具非常多,有家喻戶曉的 Grunt、Gulp、Webpack,也有各大公司團(tuán)隊開源的構(gòu)建工具,這里通過 Github 的 Star 數(shù)量來簡單的對比下各個工具的流行度:

stars.png

如果把工具按類型分可以分為這三類:

  1. 基于任務(wù)運(yùn)行的工具:
    Grunt、Gulp
    它們會自動執(zhí)行指定的任務(wù),就像流水線,把資源放上去然后通過不同插件進(jìn)行加工,它們包含活躍的社區(qū),豐富的插件,能方便的打造各種工作流。

  2. 基于模塊化打包的工具:
    Browserify、Webpack、rollup.js
    有過 Node.js 開發(fā)經(jīng)歷的應(yīng)該對模塊很熟悉,需要引用組件直接一個 require 就 OK,這類工具就是這個模式,還可以實現(xiàn)按需加載、異步加載模塊。

  3. 整合型工具:
    Yeoman、FIS、jdf、Athena、cooking、weflow
    使用了多種技術(shù)棧實現(xiàn)的腳手架工具,好處是即開即用,缺點就是它們約束了技術(shù)選型,并且學(xué)習(xí)成本相對較高。

四、構(gòu)建工具選型

在做選型的時候,我們往往會考慮以下幾個因素:

  1. 是否符合團(tuán)隊的技術(shù)棧
  2. 是否符合項目需求
  3. 生態(tài)圈是否完善、社區(qū)是否活躍

還是排除 1、2 主觀的因素,我們在不同類型的工具中選擇幾個熱門(滿足因素3),也就是:Grunt、Gulp、Webpack、Yeoman 看看它們的工作流、優(yōu)劣點以及適用場景。

1、Grunt & Gulp

工作流:
這兩款工具都是基于任務(wù)類型,所以它們的工作流是一致的:

gulp_workflow.png

可以看到它們打包的策略通常是 All in one,最后頁面還是引用 css、img、js,開發(fā)流程與徒手開發(fā)相比并無差異。

特點與不足
Grunt
Grunt 是老牌的構(gòu)建工具,特點是配置驅(qū)動,你需要做的就是了解各種插件的功能,然后把配置整合到 Gruntfile.js 中,可以看下面的配置例子,簡單直接:

module.exports = function(grunt) {
  grunt.initConfig({
    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
      options: {
        globals: {
          jQuery: true
        }
      }
    },
    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['jshint']);
};

Grunt 缺點也是配置驅(qū)動,當(dāng)任務(wù)非常多的情況下,試圖用配置完成所有事簡直就是個災(zāi)難;再就是它的 I/O 操作也是個弊病,它的每一次任務(wù)都需要從磁盤中讀取文件,處理完后再寫入到磁盤,例如:我想對多個 less 進(jìn)行預(yù)編譯、壓縮操作,那么 Grunt 的操作就是:

讀取 less 文件 -> 編譯成 css -> 存儲到磁盤 -> 讀取 css -> 壓縮處理 -> 存儲到磁盤

這樣一來當(dāng)資源文件較多,任務(wù)較復(fù)雜的時候性能就是個問題了。

Gulp
Gulp 特點是代碼驅(qū)動,寫任務(wù)就和寫普通的 Node.js 代碼一樣:

var gulp = require('gulp');
var pug = require('gulp-pug');
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');

gulp.task('html', function(){
  return gulp.src('client/templates/*.pug')
    .pipe(pug())
    .pipe(gulp.dest('build/html'))
});

gulp.task('css', function(){
  return gulp.src('client/templates/*.less')
    .pipe(less())
    .pipe(minifyCSS())
    .pipe(gulp.dest('build/css'))
});

gulp.task('default', [ 'html', 'css' ]);

再一個對文件讀取是流式操作(Stream),也就是說一次 I/O 可以處理多個任務(wù),還是 less 的例子,Gulp 的流程就是:

讀取 less 文件 -> 編譯成 css -> 壓縮處理 -> 存儲到磁盤

Gulp 作為任務(wù)類型的工具沒有明顯的缺點,唯一的問題可能就是完成相同的任務(wù)它需要寫的代碼更多一些,所以除非是項目有歷史包袱(原有項目就是基于 Grunt 構(gòu)建)在 Grunt 與 Gulp 對比看來還是比較推薦 Gulp!

適用場景:
通過上面的介紹可以看出它們側(cè)重對整個過程的控制管理,實現(xiàn)簡單、對架構(gòu)無要求、不改變開發(fā)模式,所以非常適合前端、小型、需要快速啟動的項目。

2、Webpack
Webpack 是目前最熱門的前端資源模塊化管理和打包工具,還是先通過一張圖大致了解它的運(yùn)行方式:

工作流

webpack_workflow.png

特點與不足
Webpack 的特點:

  1. 把一切都視為模塊:不管是 CSS、JS、Image 還是 HTML 都可以互相引用,通過定義 entry.js,對所有依賴的文件進(jìn)行跟蹤,將各個模塊通過 loader 和 plugins 處理,然后打包在一起。
  2. 按需加載:打包過程中 Webpack 通過 Code Splitting 功能將文件分為多個 chunks,還可以將重復(fù)的部分單獨提取出來作為 commonChunk,從而實現(xiàn)按需加載。

Webpack 也是通過配置來實現(xiàn)管理,與 Grunt 不同的時,它包含的許多自動化的黑盒操作所以配置起來會簡單很多(但遇到問題調(diào)試起來就很麻煩),一個典型的配置如下:

module.exports = {
    //插件項
    plugins: [commonsPlugin],
    //頁面入口文件配置
    entry: {
        index : './src/js/page/index.js'
    },
    //入口文件輸出配置
    output: {
        path: 'dist/js/page',
        filename: '[name].js'
    },
    module: {
        //加載器配置
        loaders: [
            { test: /\.css$/, loader: 'style-loader!css-loader' },
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
            { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    //其它解決方案配置
    resolve: {
        root: '/Users/Bell/github/flux-example/src', //絕對路徑
        extensions: ['', '.js', '.json', '.scss'],
        alias: {
            AppStore : 'js/stores/AppStores.js',
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js'
        }
    }
};

Webpack 的不足:

  1. 上手比較難:官方文檔混亂、配置復(fù)雜、難以調(diào)試(Webpack2 已經(jīng)好了很多)對于新手而言需要經(jīng)歷踩坑的過程;
  2. 對于 Server 端渲染的多頁應(yīng)用有點力不從心:Webpack 的最初設(shè)計就是針對 SPA,所以在處理 Server 端渲染的多頁應(yīng)用時,不管你如何 chunk,總不能真正達(dá)到按需加載的地步,往往要去考慮如何提取公共文件才能達(dá)到最優(yōu)狀態(tài)。

模塊化與組件化
提到 Webpack 就不得不說它的模塊化加載方式,先來看下傳統(tǒng)的模塊化方式:

├── scripts/
│    ├── dropdown.js
│    ├── lazyload.js
│    ├── modal.js
│    └── slider.js
├── styles/
│    ├── button.less
│    ├── list.less
│    ├── modal.less
│    └── slider.less

傳統(tǒng)的模塊化基于單種編程語言,目的是為了解耦和重用,而因為前端本身的特點(需要三種編程語言配合)以及能力限制,所以不能實現(xiàn)跨資源加載也就難以實現(xiàn)組件化。

而 Webpack 打破的這種思維局限,它的 Require anything 的理念在實現(xiàn)模塊化的同時也能夠很方便實現(xiàn)組件化,借助 Webpack 就可以很輕松的實現(xiàn)這種代碼組織結(jié)構(gòu):

├──components/
│    ├── button/
│    │    ├── button.js
│    │    ├── button.less
│    │    ├── dropdwon.js
│    │    └── icon.png
│    ├── modal/
│    ├── slider/

一旦實現(xiàn)組件化,那么我們的項目開發(fā)方式和分工合作方式就可以升級,可以實現(xiàn)分組件并行開發(fā),也可以方便的引用其它項目使用的組件:

項目A

組件 開發(fā)人員
選項卡 小明
資訊列表 華生
走馬燈 諸葛
模態(tài)窗口 復(fù)用

項目B

組件 開發(fā)人員
選項卡 復(fù)用
按鈕 小迪
模態(tài)窗口 龍辰
上傳 老馬

So,可以說組件化才是目前提升大型項目多人團(tuán)隊合作效率的最佳解決方案!

適用場景:
綜上所述,Webpack 特別適合配合 React.js、Vue.js 構(gòu)建單頁面應(yīng)用以及需要多人合作的大型項目,在規(guī)范流程都已約定好的情況下往往能極大的提升開發(fā)效率與開發(fā)體驗。

OK,對于前端工程工具的介紹就到這里,希望能在大家做技術(shù)選型的時候給予一定的幫助;接下來還會帶來 Gulp、Webpack 在實際工作應(yīng)用的詳細(xì)教程。

參考文獻(xiàn)

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

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

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