首页 > 解决方案 > 如何在 babel 7.4 和 grunt 中使用 polyfill?

问题描述

在使用 babel 和 grunt 时,我遇到了 IE11 的一些问题。我需要使用一位前同事编写的新 ECMA 功能来填充一些代码,他将 babel 更新到 7.4(但没有将 babelrc 更改为使用 corejs),并且代码在 IE11 中不是 testet。所以现在代码在 Internet Explorer 中不起作用,我不得不填充,没有更深入的 babel 和 grunt 知识。我将 babelrc preset-env 更改为使用 builtIns,但无法使其运行。

我将 babelrc 更改为使用带有 builtIns 的预设环境。所以我将 useBuiltIns 设置为使用,所以 polyfills 仅在需要时包含。但随后 babel 会生成“require”语句,这些语句当然不能被浏览器解释。即使我将 useBuiltIns 设置为“entry”(而且我不知道与“usage”有什么区别),我在 IE11 的 js 控制台中得到“SCRIPT5009:“Symbol”未定义”作为错误。

package.json:
{
  "name": "xyproject",
  "version": "1.0.0",
  "dependencies": {
    "bootstrap3-dialog": "^1.35.4",
    "core-js": "^3.1.4",
    "datatables.net-bs": "^1.10.19",
    "datatables.net-buttons-bs": "^1.5.6",
    "datatables.net-colreorder-bs": "^1.5.1",
    "datatables.net-responsive": "^2.2.3",
    "datatables.net-responsive-bs": "^2.2.3",
    "normalize-scss": "^7.0.1"
  },
  "devDependencies": {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-transform-object-assign": "^7.2.0",
    "@babel/preset-env": "^7.5.5",
    "babel-preset-minify": "^0.5.0",
    "grunt": "^1.0.4",
    "grunt-babel": "^8.0.0",
    "grunt-concurrent": "^2.3.1",
    "grunt-contrib-clean": "^2.0.0",
    "grunt-contrib-compass": "^1.1.1",
    "grunt-contrib-concat": "^1.0.1",
    "grunt-contrib-sass": "^1.0.0",
    "grunt-contrib-uglify": "^3.4.0",
    "grunt-contrib-uglify-es": "^3.3.0",
    "grunt-contrib-watch": "^1.1.0",
    "grunt-newer": "^1.3.0",
    "grunt-notify": "^0.4.5",
    "jit-grunt": "^0.10.0",
    "time-grunt": "^1.4.0",
    "uglify-es": "github:mishoo/UglifyJS2#harmony"
  }
}

.babelrc:

{
  "sourceType": "unambiguous",
  "sourceMap": true,
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-transform-template-literals",
    "@babel/plugin-transform-object-assign"
  ],
  "presets": [
    [
      "@babel/preset-env", {
        "debug": false,
        "useBuiltIns": "usage",
        "corejs": 3,
        "targets": {
          "ie": "9"
        }
      }
    ],
    [
      "minify", {
        "mangle": true,
        "deadcode": true,
        "simplify": true,
        "builtIns": false
      }
    ]
  ]
}

gruntfile.js:

'use strict';

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('../../package.json'),

    config: {
      sass:         'assets/scss',
      css:          'assets/css',
      js:           'assets/js',
      templates:    'assets/templates',
      build:        'assets/build',
      node_modules: 'node_modules'
    },

    // notify if process is done
    notify: {
      watch_js: {
        options: {
          title: 'Task Complete',
          message: 'JS Tasks are completed'
        }
      },
      watch_css: {
        options: {
          title: 'Task Complete',
          message: 'SCSS/CSS Tasks are completed'
        }
      }
    },

    // Bablify our js files - we're now able
    // to write JS code in newest style :)
    // Babel will transpile the code for elder browsers
    babel: {
      options: {
        // babelrc: false,
        // sourceType: 'unambiguous',
        // sourceMap: true,
        // presets: [
        //   [
        //     '@babel/preset-env', {
        //       targets: {
        //         ie: '9'
        //       }
        //     },
        //   ],
        //   [
        //     'minify', {
        //       mangle: true,
        //       deadcode: true,
        //       simplify: true,
        //       // evaluate: true
        //     }
        //   ]
        // ],
      },
      dist: {
        files: {
          '<%= config.build %>/backend.min.js':         '<%= config.build %>/backend.min.js',
          '<%= config.build %>/backend_tables.min.js':  '<%= config.build %>/backend_tables.min.js',
          '<%= config.build %>/backend_pages.min.js':   '<%= config.build %>/backend_pages.min.js',
          '<%= config.build %>/wysiwyg.min.js':         '<%= config.build %>/wysiwyg.min.js',
          '<%= config.build %>/dataview.min.js':        '<%= config.build %>/dataview.min.js',
          '<%= config.build %>/reporting.min.js':       '<%= config.build %>/reporting.min.js',
          // '<%= config.build %>/search.min.js':          '<%= config.build %>/search.min.js',
        }
      }
    },

    build: {
      clean: {
        tasks: ['clean']
      },
      css: {
        tasks: ['sass']
      },
      js: {
        tasks: [
          'concat',
          'babel',
          'uglify',
          'remove_unnecessary_files'
        ]
      }
    },

    // removes all files from folder
    clean: ['<%= config.build %>/'],

    // compiles scss to css
    sass: {
      dist: {
        options: {
          style: 'compressed',
          compass: false,
          loadPath: [
            'node_modules/normalize-scss/sass'
          ]
        },
        files: {
          '<%= config.build %>/main.css': [
            '<%= config.sass %>/main.scss',
            '<%= config.node_modules %>/bootstrap3-dialog/src/css/bootstrap-dialog.css'
          ]
        }
      }
    },

    concat: {
      options: {
        sourceMap: true
      },
      libs: {
        src: [
          '<%= config.node_modules %>/@babel/polyfill/dist/polyfill.min.js',
          '<%= config.js %>/libs/jquery.min.js',
          '<%= config.js %>/libs/jquery-ui.min.js',
          '<%= config.js %>/libs/jquery.validate.js',

          // bootstrap-4.1.3-dist/js/bootstrap.bundle.js
          // '<%= config.js %>/bootstrap-4.1.3-dist/js/bootstrap.js',
          // '<%= config.js %>/bootstrap-4.1.3-dist/js/bootstrap.bundle.js',

          '<%= config.js %>/libs/bootstrap.min.js',
          '<%= config.js %>/libs/bootstrap-select.js',
          '<%= config.js %>/libs/bootstrap-datepicker.js',
          '<%= config.js %>/libs/bootstrap-tagsinput.js',
          '<%= config.js %>/libs/jquery.mCustomScrollbar.min.js',
          '<%= config.js %>/libs/icheck.min.js',
          // '<%= config.js %>/libs/jquery.tagsinput.min.js',
          '<%= config.js %>/libs/jquery.noty.js',
          '<%= config.js %>/libs/noty-layouts/topRight.js',
          '<%= config.js %>/libs/noty-themes/default.js',
          '<%= config.js %>/libs/jquery.nestable.js',
          '<%= config.js %>/libs/fileinput.min.js',
          '<%= config.js %>/libs/moment.min.js',
          '<%= config.js %>/libs/plugins.js',
          '<%= config.js %>/libs/actions.js',
          '<%= config.js %>/libs/jquery.cookie.js',
          '<%= config.js %>/libs/spin.min.js',
          '<%= config.js %>/libs/select2.js',
          '<%= config.js %>/libs/icheck_custom.js',
          '<%= config.js %>/libs/bootstrap-typeahead.min.js',
          '<%= config.js %>/libs/daterangepicker.js',
          // if you want to add Datatatables plugins, see the following lines on how to do so:
          //          '<%= config.js %>/libs/datatables.js',
          '<%= config.node_modules %>/datatables.net/js/jquery.dataTables.js',
          '<%= config.node_modules %>/datatables.net-bs/js/dataTables.bootstrap.js',
          '<%= config.node_modules %>/datatables.net-buttons/js/dataTables.buttons.js',
          '<%= config.node_modules %>/datatables.net-buttons/js/buttons.colVis.js',
          '<%= config.node_modules %>/datatables.net-buttons-bs/js/buttons.bootstrap.js',
          '<%= config.node_modules %>/datatables.net-colreorder/js/dataTables.colReorder.js',
          '<%= config.node_modules %>/datatables.net-responsive/js/dataTables.responsive.js',
          '<%= config.node_modules %>/datatables.net-responsive-bs/js/responsive.bootstrap.js',
          '<%= config.node_modules %>/bootstrap3-dialog/src/js/bootstrap-dialog.js',

          '<%= config.js %>/libs/lodash.min.js',

          '<%= config.js %>/libs/filesaver.js',
          '<%= config.js %>/libs/queue.js',
        ],
        dest: '<%= config.build %>/libs.min.js'
      },
      backend: {
        src: [
          '<%= config.js %>/globals.js',
          '<%= config.js %>/backend.js',
          '<%= config.js %>/datatable.js',
          '<%= config.js %>/action.js',
          '<%= config.js %>/menu.js',
          '<%= config.js %>/validate.js',
          '<%= config.js %>/ajax.js',
          '<%= config.js %>/adv_search.js',
          '<%= config.js %>/massupdate.js',
          '<%= config.js %>/storage.js',
          '<%= config.js %>/widgets.js',
          '<%= config.js %>/sessionTimer.js',
          '<%= config.js %>/widgets.js',
          '<%= config.js %>/impersonate.js',
          '<%= config.js %>/helper/*.js'
        ],
        dest: '<%= config.build %>/backend.min.js'
      },
      pages: {
        src: [
          '<%= config.js %>/page_*.js',
        ],
        dest: '<%= config.build %>/backend_pages.min.js'
      },
      dataview: {
        src: [
          '<%= config.js %>/dataview/*.js',
        ],
        dest: '<%= config.build %>/dataview.min.js'
      },
      reporting: {
        src: [
          '<%= config.js %>/reporting/*.js',
        ],
        dest: '<%= config.build %>/reporting.min.js'
      },
      tables: {
        src: [
          '<%= config.js %>/table_*.js',
          '<%= config.js %>/table_search/type_base.js',
          '<%= config.js %>/table_search/*.js',
        ],
        dest: '<%= config.build %>/backend_tables.min.js'
      },
      /*search: {
        src: [
          // '<%= config.js %>/table_*.js',
          '<%= config.js %>/table_search/*.js',
        ],
        dest: '<%= config.build %>/search.min.js'
      },*/
      wysiwyg: {
        src: [
          '<%= config.js %>/wysiwyg.js',
        ],
        dest: '<%= config.build %>/wysiwyg.min.js'
      }
    },

    watch: {
      options: {
        spawn: false // add spawn option in watch task
      },
      css: {
        files: [
          '<%= config.sass %>/*.scss',
          '<%= config.sass %>/*/**'
        ],
        tasks: [
          'sass',
          'notify:watch_css'
        ]
      },
      devIe: {
        files: [
          '<%= config.js %>/*.js',
          '<%= config.js %>/*/**'
        ],
        tasks: [
          'concat',
          'babel',
          'notify:watch_js'
        ]
      },
      js_dev: {
        files: [
          '<%= config.js %>/*.js',
          '<%= config.js %>/*/**'
        ],
        tasks: [
          'concat',
          // 'babel',
          // 'rename_js_files',
          'notify:watch_js'
        ]
      },
      livereload: {
        options: {
          livereload: true
        },
        files: ['<%= config.build %>**/*.js', '<%= config.build %>/main.css']
      }
    },

    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */',
        sourceMap: {
          includeSources: true
        },
        report: 'gzip',
        output: {
          comments: false
        },
        sourceMapIn: function(path) {
          return path + '.map';
        }
      },
      dist: {
        files: {
          '<%= config.build %>/libs.min.js': ['<%= config.build %>/libs.min.js'],
          '<%= config.build %>/backend.min.js': ['<%= config.build %>/backend.min.js'],
          '<%= config.build %>/backend_tables.min.js': ['<%= config.build %>/backend_tables.min.js'],
          '<%= config.build %>/backend_pages.min.js': ['<%= config.build %>/backend_pages.min.js'],
          '<%= config.build %>/wysiwyg.min.js': '<%= config.build %>/wysiwyg.min.js',
          '<%= config.build %>/dataview.min.js': ['<%= config.build %>/dataview.min.js'],
          '<%= config.build %>/reporting.min.js': ['<%= config.build %>/reporting.min.js'],
          '<%= config.build %>/search.min.js': ['<%= config.build %>/search.min.js'],
        }
      }
    },

    concurrent: {
      options: {
        logConcurrentOutput: true
      },
      dev: {
        tasks: ['watch:js_dev', 'watch:css', 'watch:livereload']
        // tasks: ['watch:js_dev', 'watch:css']
      },
      devIe: {
        tasks: ['watch:devIe', 'watch:css']
        // tasks: ['watch:js_dev', 'watch:css']
      }
    }
  });

  // grunt.loadNpmTasks('grunt-contrib-sass');
  // grunt.loadNpmTasks('grunt-contrib-watch');
  // grunt.loadNpmTasks('grunt-contrib-concat');
  // grunt.loadNpmTasks('grunt-contrib-uglify');
  // grunt.loadNpmTasks('grunt-contrib-handlebars');
  // grunt.loadNpmTasks('grunt-notify');
  // grunt.loadNpmTasks('grunt-concurrent');
  grunt.loadNpmTasks('grunt-contrib-uglify-es');

  grunt.registerMultiTask('build', 'build the given task', function() {
    grunt.task.run( this.data.tasks );
  });

  grunt.registerTask('remove_unnecessary_files', 'Remove *.js to *.min.js', () => {
    let fs,
      fileNames,
      fileName;

    fs = require('fs');

    fileNames = [
      'backend_tables.js',
      'backend_tables.js.map',
      'backend_tables.min.js.map',
      'backend.js',
      'backend.js.map',
      'backend.min.js.map',
      'backend_pages.js',
      'backend_pages.js.map',
      'backend_pages.min.js.map',
      'libs.js',
      'libs.js.map',
      'libs.min.js.map',
      'main.css.map'
    ];

    for (fileName in fileNames) {
      if (fs.existsSync(grunt.config.data.config.build + '/' + fileNames[fileName])) {
        fs.unlink(grunt.config.data.config.build + '/' + fileNames[fileName], (err) => {
          if (err) {
            grunt.log.error(`Remove ${grunt.config.data.config.build + '/' + fileNames[fileName]} failed: ${err}`);
          } else {
            grunt.log.ok(`Remove ${grunt.config.data.config.build + '/' + fileNames[fileName]} done`);
          }
        });
      }
    }

  });

  grunt.registerTask('rename_js_files', 'Rename *.js to *.min.js', function() {
    var fs,
        libsFileName,
        libsMinFileName,
        backendFileName,
        backendMinFileName;

    fs = require('fs');
    libsFileName = grunt.config.data.config.build + '/libs.js';
    libsMinFileName = grunt.config.data.config.build + '/libs.min.js';

    backendFileName = grunt.config.data.config.build + '/backend.js';
    backendMinFileName = grunt.config.data.config.build + '/backend.min.js';

    fs.rename(libsFileName, libsMinFileName, function(err) {
      if (err) {
        grunt.log.error('ERROR: ' + err);
      }
    });

    fs.rename(backendFileName, backendMinFileName, function(err) {
      if (err) {
        grunt.log.error('ERROR: ' + err);
      }
    });
  });

  // grunt.registerTask('default', ['build', 'watch:css', 'watch:js']);
  grunt.registerTask('watch:dev', ['build', 'concurrent:dev']);
  // grunt.registerTask('watch:dev-ie', ['build', 'concurrent:devIe']);
  grunt.registerTask('watch:dev-ie', ['watch:devIe', 'watch:css', 'watch:livereload']);

  require('jit-grunt')(grunt);
};

我正在使用“./node_modules/.bin/grunt watch:dev-ie”运行应用程序,然后更改一些 javascript 代码以触发 livereload,因此执行“devIe”任务并且 babel 将转译代码。如果我在 babelrc 代码中使用“条目”作为 useBuiltIn 选项的值,但我得到“符号未定义”。当我使用“usage”作为值时,babel 将 require 语句添加到我缩小的 js 文件中,我在 js 控制台中得到“require is undefined”。

我用 IE11 测试代码。我不想使用 Browserify 或 webpack,因为这会使事情变得更复杂。谁能告诉我我的配置中缺少什么以使事情正常进行?我原以为 babel 不会创建现代浏览器无法解释的 require 语句,需要由 webpack 或其他东西翻译才能使事情正常运行。我只想扩展我的 babel / grunt 配置来填充 javascript 代码以在 IE11 中工作。也许我在 package.json 中也缺少一个包?

标签: gruntjsinternet-explorer-11babeljscore-js

解决方案


推荐阅读