如何让node运行es6模块文件,及其原理最新版本的node几乎支持最新版ECMAScript的所有特性,但有一个特性有直到现在还没有得到支持。这是自ES2015以来定义的模块化机制。现在我们很多项目都是使用es6模块化规范来写代码的,包括node项目,所以如果node不能运行es6模块文件会很不方便。让node运行es6模块文件有两种方式:转码es6模块到commonjs模块hook节点的require机制,直接让node的require加载import/export1。将es6模块转码成commonjs模块,因为node除了import/export语法几乎都支持,所以我们只需要将import/export转成require/exports即可,不需要转码其他语法。例如以下项目:-package.json-src/-index.js-print.js-...#package.json{"main":"lib/index.js"#转码src中的源文件通过工具目录进入lib目录}#src/index.jsimportprintfrom'./print';print('index');exportdefaultprint;#src/print.jsexportdefaultstr=>{console.log('print:'+str);};由于src目录下的源文件都是es6模块化规范,node不能直接运行,所以需要转码成commonjs兼容的代码。这个过程有两种选择:如果你不会单独使用src目录下的一个文件,而只使用src/index.js作为入口文件,你可以将src目录下的文件打包成一个文件发送到库/索引。js:该方法推荐使用工具rollup。如果需要单独使用src目录下的文件,需要将src目录下的文件一一转码到lib目录下:该方法推荐使用工具gulp+babel1.1使用rollup打包文件将src目录下的一个文件打包成lib/index.js相关文件:#rollup.config.jsexportdefault{input:'src/index.js',output:{file:'lib/index.js',format:'cjs',},};#package.json{"scripts":{"build":"rollup-c"},"devDependencies":{"rollup":"^0.66.4"}}运行命令:npmrunbuild结果:#lib/index.js'usestrict';varprint=str=>{console.log('print:'+str);};print('index');module.exports=print;1.2使用gulp+babel对其中的文件进行一对一转码src目录到lib目录下的相关文件:#build.jsconstgulp=require('gulp');constbabel=require('gulp-babel');gulp.task('babel',()=>gulp.src('src/**/*.js').pipe(babel({plugins:['@babel/plugin-transform-modules-commonjs']})).pipe(gulp.dest('lib')));gulp.series('babel')();#package.json{"scripts":{"建造”:”nodebuild.js"},"devDependencies":{"@babel/core":"^7.1.2","@babel/plugin-transform-modules-commonjs":"^7.2.0","gulp":"^4.0.0","gulp-babel":"^8.0.0"}}运行命令:npmrunbuild结果:#lib/index.js"usestrict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void0;var_print=_interopRequireDefault(require("./print"));function_interopRequireDefault(obj){returnobj&&obj.__esModule?obj:{default:obj};}(0,_print.default)('index');var_default=_print.default;exports.default=_default;#lib/print.js"usestrict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void0;var_default=str=>{console.log('print:'+str);};exports.default=_default;2.hook节点的require机制,loadimport直接/export机制一般会hooknode的require机制,劫持require捕获的源文件代码,将源代码转码为commonjs规范,然后在require机制的原始代码流中传输给盗版者。三方npm包提供了这个添加hooks的功能。babel-register就是通过这种方式来达到node运行es6模块文件的目的。2.1使用babel-register直接运行es6模块文件示例目录:-package.json-src/-entry.js#这里多了一个入口文件,专门用来注册babel-register-index.js-print.js-..相关文件:#package.json{"scripts":{"run":"nodesrc/entry.js"},"devDependencies":{"@babel/core":"^7.1.2","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/register":"^7.0.0"}}#src/entry.js#入口文件一定要写使用commonjs规范,因为还是Noregistrationhookrequire('@babel/register')({plugins:['@babel/plugin-transform-modules-commonjs']});require('./index');#src/index.jsimportprintfrom'./print';print('index');#src/print.jsexportdefaultstr=>{console.log('print:'+str);};运行:npmrunrunresult:#commandlineprintprint:索引的方式不建议在生产环境使用,因为中间转码会造成额外的性能损失,只能在开发模式使用。2.2使用babel-node直接运行es6模块文件babel-node封装了babel-register,提供了一种直接在命令行运行es6模块文件的便捷方式。示例目录:-package.json-src/-index.js-print.js-...相关文件:#package.json{"scripts":{"run":"babel-nodesrc/index.js--插件@babel/plugin-transform-modules-commonjs"},"devDependencies":{"@babel/core":"^7.1.2","@babel/node":"^7.2.0","@babel/plugin-transform-modules-commonjs":"^7.2.0"}}#src/index.jsimportprintfrom'./print';print('index');#src/print.jsexportdefaultstr=>{console.log('print:'+str);};运行:npmrunrunresult:#commandlineprintprint:index这种方法不推荐在生产环境使用,只推荐在开发模式使用。3.链接es6指ECMAScript2015es7指ECMAScript2016es8指ECMAScript2017es9指ECMAScript2018在写这篇文章的时候,ECMAScript2018已经发布了。更多后续博客,查看https://github.com/senntyou/blogs作者:沈玉之(@senntyou)版权声明:免费转载-非商业-非衍生-保留署名(CreativeCommons3.0许可)
