大家好,我是Kason。在最近发布的Nodev18.6.0中,引入了一个实验性的特性ESMLoaderHooksAPI。如果他最终落地,很可能会成为改变前端工程未来的一个特性。这篇文章就来说说他吧。欢迎加入人类优质前端框架群,将本文作为参考:CustomESMloaders:Who,what,when,where,why,how特性介绍用过webpack的朋友一定知道有是webpack中loader的一个概念,用来加载和处理不同类型的文件,比如css-loader,url-loader。loader的执行顺序取决于webpack内部解析和遍历文件树的顺序。今天要介绍的ESMLoaderHooks和webpackloader类似,只是文件树的解析和遍历是由Node.js原生支持的ESM规范决定的(而不是打包工具)。通过定义不同的加载器,可以在不使用工程工具的情况下处理项目中的每个ESM模块。例如在命令行通过--experimental-loader命令启用该特性后,执行如下语句:$>node--loaderredirect.mjsapp.mjs其中,app.mjs为待处理的源文件,而.mjs后缀指的是文件表示为ESM模块(对应的,.cjs后缀指的是CJS模块)。--loader用于指定一个自定义的ESMLoader,这里指定redirect.mjs,app.mjs会被redirect.mjs处理。redirect.mjs代码如下://redirect.mjsexportfunctionresolve(specifier,context,nextResolve){letredirect='app.prod.mjs';switch(process.env.NODE_ENV){case'development':redirect='app.dev.mjs';休息;case'test':redirect='app.test.mjs';休息;}returnnextResolve(redirect);}redirect.mjs会根据Node当前环境重写文件导入路径。比如在开发环境中(process.env.NODE_ENV==='development'),app.mjs经过redirect.mjs处理后会重定向到app.dev.mjs。ESMLoaderHooksAPI中之所以有Hooks,是因为每个自定义ESMLoader都可以像钩子(Hooks)一样连接到其他自定义ESMLoader(或者Node.js默认提供的ESMLoader)。例如,在下面的语句中:$>node--loaderc.mjs--loaderb.mjs--loadera.mjsapp.mjsapp.mjs将依次被三个自定义的ESMLoaderabc处理。整个过程就像一个promise.then链(事实上,每个ESM加载器确实返回一个promise)。实际示例要查看更接近日常开发的示例,请考虑以下ESM模块://app.tsximportReactDOMfrom'react-dom/client';import{BrowserRouter,useRoutes,}from'react-router-dom';importApp来自'./AppHeader.tsx';从'https://example.com/routes.json'导入路由断言{type:'json'};import'./global.css'assert{type:'css'};constroot=ReactDOM.createRoot(document.getElementById('root'));root.render(
