前端的打包工具

本文當時寫在本地,發現換電腦很不是方便,在這裏記錄下。javascript

:pray: 前端的打包工具

打包工具能夠更好的管理htmlcssjavascript,使用能夠錦上添花,不使用也不要緊。css

1. 前言

1.1 前端

前端三劍客:結構層 html,表現層 css,行爲層 javascripthtml

html比如是房子的地基,cssjavascript是房子的建築材料,這三個部分一塊兒組成個漂亮的房子。咱們不能把他們分開說,某某部分是個房子,只有三個一塊兒才能組成一個漂亮的房子 。前端

1.2 JavaScript 的簡介(參考阮一峯的ES6入門簡介)

這幾年,javascript 發展很是快速,特別是在2015年,更是有一個質的飛躍。vue

1.2.1 ECMA

說到 JavaScript,就要說下Web標準的組織協會,ECMA,它是「European Computer Manufactures Association」的縮寫,中文稱 歐洲計算機制造聯合會,1961年成立,旨在創建統一的電腦操做格式標準--包括程序語言和輸入輸出的組織。java

1.2.2 JavaScript

2015年,JavaScript 引入許多新的語法糖,並且制定過程中,還有不少組織和我的不斷提交新功能。事情很快就變得清楚了,不可能在一個版本里麪包括全部將要引入的功能。node

常規的作法是先發布 6.0 版,過一段時間再發 6.1 版,而後是 6.2 版、6.3 版等等 ,這個2015年以前 JavaScript 如今習慣稱爲ECMAScript5,而以後稱爲ECMAScript6。react

標準委員會商定後最終決定,標準在每一年的 6 月份正式發佈一次,做爲當年的正式版本。接下來的時間,就在這個版本的基礎上作改動,直到下一年的 6 月份,草案就天然變成了新一年的版本。這樣一來,就不須要之前的版本號了,只要用年份標記就能夠了。webpack

所以,ES6 既是一個歷史名詞,也是一個泛指,含義是 5.1 版之後的 JavaScript 的下一代標準,涵蓋了 ES201五、ES201六、ES2017 等等,而 ES2015 則是正式名稱,特指該年發佈的正式版本的語言標準。本書中提到 ES6 的地方,通常是指 ES2015 標準,但有時也是泛指「下一代 JavaScript 語言」。es6

  • 問題一:關於ECMAScript 和 JavaScript 是什麼關係 ?

    回答:從如今的角度來看,兩者是能夠互換的。即ECMAScript是JavaScript ,JavaScript 是ECMAScript。

  • 問題二:ECMAScript 6 和 ECMAScript 2015 是什麼關係 ?

    回答:ECMAScript 6泛指下一代 JavaScript 語言,ECMAScript 2015指的是 2015年的 JavaScript 標準;

  • 總結

    // es6 泛指下一代 JavaScript 語言,當時部分人也會認爲特指ES2015
    ECMAScript6.0  =  ECMAScript2015 = es2015  =  es6(部分人會這麼認爲)
    ECMAScript6.1  =  ECMAScript2016 = es2016  =  es7(部分人會這麼認爲)
    ECMAScript6.2  =  ECMAScript2017 = es2017  =  es8(部分人會這麼認爲)
    
    複製代碼
1.2.3 瀏覽器的遭遇

很尷尬的是,JavaScript發展很快,可是瀏覽器跟不上腳本更新的進度。一方面給出了標準,一方面卻不能直接在瀏覽器上使用。

這就出現了 BabelBabel自稱是 JavaScript 編譯器,它的做用就是將ES6新語法轉成ES5,即如今瀏覽器可識別的腳本(基本如今是針對老版 IE 內核)。

可是使用 Babel 編譯也有缺陷,那就是每一次保存,都須要手動的使用命令行編譯,並且編譯過程當中還須要相關聯的包配合使用,很繁瑣。因此,打包工具就出現了,它能夠幫助作這些繁瑣的工做。

2. 打包工具

2.1 介紹

僅介紹 4 款主流的打包工具:gruntgulpwebpackrollup,以發佈時間爲順序。

  1. Grunt:最老牌的打包工具,它運用配置的思想來寫打包腳本,一切皆配置,因此會出現比較多的配置項,諸如option,src,dest等等。並且不一樣的插件可能會有本身擴展字段,認知成本高,運用的時候須要明白各類插件的配置規則。

  2. Gulp:用代碼方式來寫打包腳本,而且代碼採用流式的寫法,只抽象出了gulp.src, gulp.pipe, gulp.dest, gulp.watch 接口,運用至關簡單。更易於學習和使用,使用gulp的代碼量能比grunt少一半左右。

  3. Webpack: 是模塊化管理工具和打包工具。經過 loader 的轉換,任何形式的資源均可以視做模塊,好比 CommonJs 模塊、AMD 模塊、ES6 模塊、CSS、圖片等。它能夠將許多鬆散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還能夠將按需加載的模塊進行代碼分隔,等到實際須要的時候再異步加載。它定位是模塊打包器,而 Gulp/Grunt 屬於構建工具。Webpack 能夠代替 Gulp/Grunt 的一些功能,但不是一個職能的工具,能夠配合使用。

  4. Rollup:下一代 ES6 模塊化工具,最大的亮點是利用 ES6 模塊設計,利用tree-shaking生成更簡潔、更簡單的代碼。通常而言,對於應用使用 Webpack,對於類庫使用 Rollup;須要代碼拆分(Code Splitting),或者不少靜態資源須要處理,再或者構建的項目須要引入不少 CommonJS 模塊的依賴時,使用 webpack。代碼庫是基於 ES6 模塊,並且但願代碼可以被其餘人直接使用,使用 Rollup。

2.2 使用總結

:point_right: Grunt:MPA,老牌打包工具,基於文件爲媒介(運行慢,零散的腳本文件一當多起來就受到影響

:point_right: Gulp:MPA,易學,基於 nodejs 的 steam 流打包 :point_right: Webpack:SPA,目前最強大的打包工具,可是過於臃腫,如何單純打包js不推薦

:point_right: Roleup:MPA,tree-shaking特性(針對es6,按需打包,多餘的不要,目前(2018,vuex,react主流使用)

2.3 如何選擇

若是你一個都不熟悉的話,那麼我直接推薦 webpack,官方文檔很是詳細,更新頻率很高。並且在其餘的打包工具在處理非網頁文件(好比svg, png, vue等)基本仍是須要藉助它來實現。最關鍵如今的腳手架主流依舊是它。

若是在處理文件須要關注前端三劍客的話,那麼 gruntgulp 會更好點,這二者我直接推薦 gulp,除非你已經很熟悉 grunt了。

若是你更加在乎腳本代碼的簡潔精煉,那麼可使用rollup

若是你還要更加精煉一點,這裏新出來一個新的打包工具,免插件式parcel

3. 我的打包配置

在打包上,我我的注重的是配置從簡單到複雜,因此我分開使用。

css 打包選擇了gulp,2個任務,3個插件,有一個插件是爲了編譯scss,若是直接使用css,那麼這個插件也能夠去除。

// 任務一:編譯
gulp.task('compile', function () {
  return gulp.src('src/scss/*.scss')
    .pipe(sass({outputStyle: 'expanded'})) // 插件一:編譯scss
    .on('error', showError)
    .pipe(autoprefixer({ // 插件二:自動添加瀏覽器前綴
      browsers: ['> 1%', 'last 4 versions'],
      cascade: false,
      remove: true
    }))
    .pipe(cleanCss({ // 插件三:壓縮樣式
      compatibility: 'ie8',
      format: 'keep-breaks'
    }))
    .pipe(gulp.dest('../dist/css'));
})
// 任務二:觀察
gulp.task('watch', function(){
  gulp.watch('src/scss/*.scss', ['compile'])
})
複製代碼

ECMAScript 我的如今基本使用es6,因此在打包腳本上我選擇了rollup,只提取有用的代碼,配置上參考react官方配置文檔

import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import { eslint } from 'rollup-plugin-eslint';
import { uglify } from 'rollup-plugin-uglify';

const env = process.env.NODE_ENV;
console.log('當前環境:%s', env);

const configs = [
  {
    input: 'src/js/index.js',
    output: {
      file: 'dist/js/index.js',
      format: 'umd',
      name: 'atom',
      banner,
      sourcemap: true
    }
  }
]

const plugins = [
  eslint({ // 檢測js代碼語法格式
    formatter: 'codeframe',
    include: [
      'src/js/**/*.js'
    ]
  }),
  resolve({ // 提取所依賴的代碼
    jsnext: true,
    main: true,
    browser: true,
    module: true
  }),
  babel({ // 編譯es6 -> es5
    exclude: 'node_modules/**' // 只編譯咱們的源代碼
  }),
  commonjs() // 將commonjs 轉成 es6 
]

export default configs.map(v => {
  v.plugins = plugins

  if (env === 'development') {
    v.watch = { // 監聽腳本的變化
      include: 'src/js/**',
      exclude: ['node_modules/**']
    }
  }

  if (env === 'production') {
    v.plugins.push(
      uglify({ // 壓縮腳本
        compress: {
          pure_getters: true,
          unsafe: true,
          unsafe_comps: true,
          warnings: false
        }
      })
    )
  }

  return v
});

複製代碼

html 我的不作任何處理,能夠在上線壓縮減小文件的體積,壓縮直接使用gulp

// 任務一
gulp.task('testHtmlmin', function () {
    var options = {
        removeComments: true,//清除HTML註釋
        collapseWhitespace: true,//壓縮HTML
        collapseBooleanAttributes: true,//省略布爾屬性的值 <input checked="true"/> ==> <input />
        removeEmptyAttributes: true,//刪除全部空格做屬性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true,//刪除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true,//刪除<style>和<link>的type="text/css"
        minifyJS: true,//壓縮頁面JS
        minifyCSS: true//壓縮頁面CSS
    };
    gulp.src('src/html/*.html')
        .pipe(htmlmin(options)) // 使用gulp-htmlmin插件
        .pipe(gulp.dest('dist/html'));
});
複製代碼
相關文章
相關標籤/搜索