前端自动化之Grunt

前端技术不断更新, 自动化工具也在迭代, grunt在一些项目中依然会用到。接下来主要分享下用grunt如何使用babel, 能够直接在前端写 es6 语法, 特别是如何能够使用 es6 中模块化语法import, export

如何配置grunt

配置grunt特别简单,一个Gruntfile.js 配置文件,安装相应的包。
具体参见grunt官网入门:http://www.gruntjs.net/getting-started

grunt能够完成哪些工作

grunt 主要通过插件完成前端自动化工作, 主要功能如下:
1. 文件合并 (grunt-contrib-concat)
2. 文件压缩 (js文件压缩,样式压缩)(grunt-contrib-uglify,grunt-contrib-cssmin)
3. 文件复制 (grunt-contrib-copy)
4. 文件清除 (grunt-contrib-clean)
5. 语法检查 (grunt-contrib-jshint)
6. es6转es5 (grunt-babel)
7. 起服务器 (grunt-contrib-connect)
8. 热加载 (connect-livereload)
9. 雪碧图 (grunt-css-sprite)
10. 单元测试 (grunt-karma)

可能遇到的问题

(1) 热加载功能需要和本地服务器一起使用,最细版本语法有更新, 如下demo

  // 监听端口号 
  var lrPort = 6699;
  // 生成脚本
  var lrSnippet = require('connect-livereload')({ port: lrPort });

  // 使用 middleware(中间件),就必须关闭 LiveReload 的浏览器插件
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var lrMiddleware = function(connect, options, middlwares) {
    return [
        lrSnippet,
        // 静态文件服务器的路径 原先写法:connect.static(options.base[0])
        serveStatic(options.base[0]),
        // 启用目录浏览(相当于IIS中的目录浏览) 原先写法:connect.directory(options.base[0])
        serveIndex(options.base[0])
    ];
  };

grunt.initConfig 中配置

    connect: {
      options: {
          port: 9000,
          host: 'localhost',
          base: 'build'
      },
      livereload: {
          options: {
              open: true,
              // 通过LiveReload脚本,让页面重新加载。
              middleware: lrMiddleware
          }
      }
    },

(2) 使用es6 的import语法,用babel转码后报错,exports undefined.
错误原因: es6 中的import,export 语法通过 bable转码后, 浏览器依然不认识。
解决方法: 安装浏览器识别的模块化umd插件,配置好babel; 并且先转码后再合并,压缩等操作。

  • 安装amd模块化

npm install –save-dev babel-plugin-transform-es2015-modules-amd

  • babel配置文件
{
  "presets": [
    ["es2015"]
  ],
  "plugins": [
    "transform-es2015-modules-umd"
  ]
}

demo示例

  • 目录结构:

这里写图片描述

  • Gruntfile.js
/**
 - @Desc: grunt 配置文件
 - @Date: 2017-12-11
 */

 // wrapper 函数
module.exports = function(grunt) {

  // 监听端口号 
  var lrPort = 6699;
  // 生成脚本
  var lrSnippet = require('connect-livereload')({ port: lrPort });

  // 使用 middleware(中间件),就必须关闭 LiveReload 的浏览器插件
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var lrMiddleware = function(connect, options, middlwares) {
    return [
        lrSnippet,
        // 静态文件服务器的路径 原先写法:connect.static(options.base[0])
        serveStatic(options.base[0]),
        // 启用目录浏览(相当于IIS中的目录浏览) 原先写法:connect.directory(options.base[0])
        serveIndex(options.base[0])
    ];
  };

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
          separator: ';'
      },
      basic: {
        src: ['build/libs/*.js'],
        dest: 'build/vendor.js'
      },
      // dist: {
      //     src: ['src/**/*.js', '!src/libs/*.js'],
      //     dest: 'build/<%= pkg.name %>.js'
      // }
      dist: {
          src: ['build/**/*.js', '!build/vendor.js', '!build/libs/*.js'],
          dest: 'build/<%= pkg.name %>.js'
      }
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        files: {
          'build/<%= pkg.name %>.min.js': ['build/<%= pkg.name %>.js'],
          'build/vendor.min.js': ['build/vendor.js'],
        }
        // src: 'build/<%= pkg.name %>.js',
        // dest: 'build/<%= pkg.name %>.min.js'
      }
    },
    connect: {
      options: {
          port: 9000,
          host: 'localhost',
          base: 'build'
      },
      livereload: {
          options: {
              open: true,
              // 通过LiveReload脚本,让页面重新加载。
              middleware: lrMiddleware
          }
      }
    },
    copy: {
      main: { expand: true, cwd: 'src', src: '**', dest: 'build/'}
    },
    clean: {
      build: ['build/**']
    },
    watch: {
      files: ['src/**', 'Gruntfile.js'],
      options: {
          livereload: lrPort
      },
      tasks: ['clean:build', 'concat', 'babel', 'uglify', 'copy:main']
    },
    babel: {
      options: {
        sourceMap: false,
        presets: ['babel-preset-es2015']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '',
          src: ['build/**/*.js', '!build/libs/*.js'],
          dest: ''
        }]
      }
    }
  });

  // 压缩
  grunt.loadNpmTasks('grunt-contrib-uglify');
  // 连接
  grunt.loadNpmTasks('grunt-contrib-concat');
  // 复制
  grunt.loadNpmTasks('grunt-contrib-copy');
  // 连接服务器
  grunt.loadNpmTasks('grunt-contrib-connect');
  // 清除
  grunt.loadNpmTasks('grunt-contrib-clean');
  // 监听文件
  grunt.loadNpmTasks('grunt-contrib-watch');
  // Babel
  grunt.loadNpmTasks('grunt-babel');

  grunt.registerTask('default', ['clean', 'copy', 'babel', 'concat', 'uglify', 'connect:livereload', 'watch']);
  grunt.registerTask('test1', ['clean', 'concat', 'uglify', 'copy:main', 'connect:livereload', 'watch']);
};
  • a.js

    export var aaa = "123456";
  • index.js

import { aaa } from './components/a.js';
console.log('aaa', aaa);  //123456

结语

  1. grunt 是任务流的模式,我们可以清晰的知道前端自动化要做的事情;
  2. grunt 对vue, react支持不是很好, 没有解析.vue文件的插件, 此时用webpack等更适合;
  3. babel内容很多,推荐中文官网文档: https://babel.docschina.org/

猜你喜欢

转载自blog.csdn.net/bob_baobao/article/details/78921810