前端的打包工具

本文当时写在本地,发现换电脑很不是方便,在这里记录下。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'));
});
复制代码
相关文章
相关标签/搜索