使用Grunt+RequireJS打包时ES6可选链语法报错求助
Grunt+RequireJS打包时ES6可选链语法解析错误的解决方法
问题场景
使用Grunt结合RequireJS打包项目时,因代码中使用了ES6可选链(?.)语法,执行grunt build命令触发解析错误,导致打包流程中断。
报错信息
Running "requirejs:desktop" (requirejs) task Error: Parse error using esprima for file: C:/projects/GitProjects/vendorgames-sonarqube/ndcasinocommon/base_common/fcga mes/vendorgames/utilities/utils.js Error: Line 17: Unexpected token . In module tree: desktop/init controller lobbyService Warning: RequireJS failed. Use --force to continue. Aborted due to warnings.
相关代码
Grunt配置代码
"use strict"; module.exports = function(grunt) { var buildVersion = grunt.option('buildVersion') || '1.0'; var currentVersion = grunt.option('currentVersion') || '1.0'; grunt.initConfig({ pkg: grunt.file.readJSON("package.json"), buildVersion: buildVersion, currentVersion: currentVersion, requirejs: { desktop: { options: { uglify2: { mangle: false }, baseUrl: "./", mainConfigFile: "desktop/init.js", name: "desktop/init", out: "desktop/___FilesToBeCached___desktop.min.js", optimize: "none" } } }, replace: { desktopReplace: { src: ["./Controller.html"], dest: "./", replacements: [{ from: "desktop-min-<%=currentVersion%>", to: "desktop-min-<%=buildVersion%>" }] } }, uglify: { desktop_build: { files: { "desktop/build.js": ["desktop/*.js", "desktop/**/*.js", "utilities/*.js"] } } } }); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-requirejs"); grunt.loadNpmTasks("grunt-text-replace"); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.file.setBase("../"); grunt.registerTask("desktop", ["requirejs:desktop"]); grunt.registerTask("desktopReplace", ["replace:desktopReplace"]); grunt.registerTask("build", ["desktop", "desktopReplace"]); };
RequireJS配置代码
require.config({ baseUrl: "./", paths: { utils: "utilities/utils", }, shim: { jqueryUI: { deps: ['jquery'] }, jqueryTouch: { deps: ['jqueryUI'] } } });
使用可选链的函数代码
function getCookie(cname) { var name = cname + "="; var ca = document?.cookie.split(";"); for (var i = 0; i < ca.length; i++) { var c = ca[i].trim(); if (c.indexOf(name) == 0) return c.substring(name.length, c.length); } return ""; }
解决方案
问题根源是默认RequireJS依赖的esprima版本不支持ES6可选链语法,可通过以下三种方式解决:
方案1:替换为支持ES6+的压缩器
修改Grunt中requirejs的配置,用terser替代uglify2(terser原生支持ES6+语法):
requirejs: { desktop: { options: { terser: { mangle: false, compress: {} }, baseUrl: "./", mainConfigFile: "desktop/init.js", name: "desktop/init", out: "desktop/___FilesToBeCached___desktop.min.js", optimize: "terser" } } }
执行命令安装terser依赖:
npm install terser --save-dev
方案2:用Babel预转译ES6+代码
- 安装依赖包:
npm install grunt-babel @babel/core @babel/preset-env --save-dev
- 在Grunt配置中添加babel任务:
grunt.initConfig({ // 保留原有配置 babel: { options: { presets: ['@babel/preset-env'] }, dist: { files: [{ expand: true, src: ['**/*.js', '!node_modules/**/*.js'], dest: 'dist/' }] } } }); // 加载babel任务 grunt.loadNpmTasks('grunt-babel'); // 修改build任务顺序,先转译再打包 grunt.registerTask("build", ["babel:dist", "desktop", "desktopReplace"]);
- 调整RequireJS配置的路径指向转译后的文件:
requirejs: { desktop: { options: { baseUrl: "./dist/", mainConfigFile: "./dist/desktop/init.js", // 其他配置不变 } } }
方案3:手动替换可选链语法(临时方案)
将所有?.语法替换为传统条件判断,无需修改打包配置:
// 替换 document?.cookie.split(";") var ca = (document && document.cookie) ? document.cookie.split(";") : [];
内容的提问来源于stack exchange,提问作者sri harsha
相关产品推荐
相关产品推荐

