天天看点

Babel和Webpack打包原理学习笔记

一、babel

babel是一个JS编译器,用来转换最新的JS语法,比如把ES6, ES7等语法转化成ES5语法,从而能够在大部分浏览器中运行。像箭头函数,就可以做转换。babel在执行过程中,分三步:先分析(parsing)、再转化、最后生成代码。

但babel只转换语法的话,一些最新的api是不转化的,比如Object.assign, Promise等。所以babel还提供了很多插件,也就是babel-pilofill。安装后,即可支持浏览器运行。babel-pilofill基于core-js和regenerator。但pilofill是引入全部的api支持,如果只用了部分api,可以只引入相应的模块。

babel还可以转换JSX语法,对React支持比较好

最后说明一下babel的presets,presets是指plugins的合集。另外plugins的执行过程是先出现先运行,但presents是先出现后执行。比如:

{
  "plugins": [
    "transform-decorators-legacy",
    "transform-class-properties"
  ]
}
           

这个是先运行transform-decorators-legacy,后运行transform-class-properties,而

{
  "presets": [
    "es2015",
    "react",
    "stage-2"
  ]
}
           

是先运行stage-2,最后运行es2015。这样做是为了更好的兼容性。

二、webpack

先提一下webpack已经是第2版了,增加了很多特性。不过我们公司的项目还没来得急更新。下面介绍的也主要基于webpack 2。

简单的说webpack是一个打包工具,打包js文件,css文件,图片,html等等,它可以分析整个项目的文件结构,确认文件之间的依赖,比如一个js文件引入了另一个js文件。在这个过程中可以合成js,压缩,加入hash等,最终生成项目文件。

webpack有几个关键概念:

  • Entry:入口文件, 可以是一个或多个入口文件。在多页面应用中,每个入口文件对应一个页面,比如我们经常有前台页面和后台管理页,它们分别对应两个入口;
  • Output:输出文件,文件名中可以带[hash]或[chunkhash], hash是经常要用到的,当生成的文件有变化时会在文件名后跟上hash串,可以避免客户端缓存;
  • Loaders:加载器,本质上是函数,接收一个资源文件返回新的文件
  • Plugins:插件
  • Externals:引入外部类库,使用external来排除js文件被打包入bundle

webpack把所有文件都当成模块(module),但是webpack只懂js,所以loaders起到关键作用。当然plugins也是重要功能。

webpack与babel通常是配合起来使用,一个典型的webpack配置文件如下:

const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;
           

Babel的presets、plugins和stage-x说明

presets:预设,即一组预先设定的插件,是babel插件的组合

presets与plugins同时存在的执行顺序

1. plugins运行在presets之前;

2. plugins配置项,按照声明顺序执行,从第一个到最后一个;

3. presets配置项,按照声明逆序执行,从最后一个到第一个(主要是为了确保向后兼容)

stage-x:指处于某一阶段的js语言提案

  • Stage 0 - 设想(Strawman):只是一个想法,可能有 Babel插件。
  • Stage 1 - 建议(Proposal):这是值得跟进的。
  • Stage 2 - 草案(Draft):初始规范。
  • Stage 3 - 候选(Candidate):完成规范并在浏览器上初步实现。
  • Stage 4 - 完成(Finished):将添加到下一个年度版本发布中。

Webpack的loader说明

loader是一种打包的方案,webpack默认只识别js结尾的文件,当遇到其他格式的文件后,webpack并不知道如何去处理。此时,我们可以定义一种规则,告诉webpack当他遇到某种格式的文件后,去求助于相应的loader。

loader的编译顺序是从右往左依次执行的。