简体   繁体   English

如何告诉作为 CDN 脚本加载的 babel 使用 ES6 模块?

[英]How to tell babel loaded as CDN script to use ES6 modules?

I am testing a React environment without a build process by loading React and Babel scripts directly from CDN.我通过直接从 CDN 加载 React 和 Babel 脚本来测试没有构建过程的 React 环境。

When I try to add ES6 modules I run into a problem: babel converts import back down to require , which is not working in the browser.当我尝试添加 ES6 模块时,我遇到了一个问题: babelimport转换回require ,这在浏览器中不起作用。

Since there is no babel config file how can I tell babel not to do this?由于没有 babel 配置文件,我怎么能告诉 babel 不要这样做呢? In other words, how can I load React with script tags from CDN and still use ES6 modules?换句话说,如何从 CDN 加载带有脚本标签的 React 并仍然使用 ES6 模块?

HTML HTML

<head>
    <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    
    <!-- babel for JSX and datatype to use modules --> 
    <script defer type="text/babel" data-type="module" src="main.js"></script>
</head>
<body>
    <div id="main"></div>
</body>

MAIN.JS (works except for the import ) MAIN.JS( import除外)

import { Drawing } from "./drawing"

const App = () => {
    
    return <div>
        <h1>Just a test</h1>
        <Drawing />
    </div>
}

const root = ReactDOM.createRoot(document.querySelector('#main'))
root.render(<App />)

PS I realise this setup is not optimised for production, but it is ideal for quickly sketching out ideas (no bundle process, no node modules folder with 30.000 packages). PS 我意识到这个设置没有针对生产进行优化,但它非常适合快速勾勒出想法(没有捆绑过程,没有包含 30.000 个包的节点模块文件夹)。

Babel standalone added support for browser-native modules in v7.10.0 (including the data-type="module" attribute), while you're using v6.当您使用 v6 时,Babel standalone在 v7.10.0 中添加了对浏览器原生模块的支持(包括data-type="module"属性)。 Removing the version number in the CDN or defining a specific one >= 7.10.0 fixes the transform-to-require issue.删除 CDN 中的版本号或定义一个 >= 7.10.0 的特定版本号可修复转换为要求的问题。

However, you have two other issues.但是,您还有另外两个问题。

The first one is trivial: ES6 native modules don't automatically resolve the file extension, so you need to do import { Drawing } from "./drawing.js" instead of import { Drawing } from "./drawing" .第一个很简单:ES6 原生模块不会自动解析文件扩展名,因此您需要执行import { Drawing } from "./drawing.js"而不是import { Drawing } from "./drawing"

Secondly though, Babel won't transform the files that you import, so that JSX would be considered invalid.其次,Babel 不会转换您导入的文件,因此 JSX 将被视为无效。 This leaves you with two options.这给您留下了两个选择。

  1. Create your own import function, and manually import like this (working example )创建您自己的导入 function,然后像这样手动导入(工作示例
async function imp(path, requestOrigin) {
  const { href } = new URL(path,
    requestOrigin
    ? requestOrigin.slice(0, requestOrigin.lastIndexOf("/"))
    : location.href
  ); // so the paths won't be messed up
  const res = await fetch(href);
  const text = await res.text();
  const { code } = Babel.transform(text, { presets: ["react"] });
  return await import(`data:application/javascript,${encodeURIComponent(code)}`);
}

Usage:用法:

const { Drawing } = await imp("./drawing.js");

// if you're in a "nested" route, e.g. "/components/Button.js", you need to provide the file
const { OtherComponent } = await imp("./hello.js", import.meta.url);
  1. okay, okay, WHY though wouldn't you use a bundler??好吧,好吧,为什么你不使用捆绑器? This is how the world works and always will (for the forseeable furture, ie)... I mean, just install parcel globally and you're like, done in two seconds with just a single command这就是世界的运作方式,并且永远如此(在可预见的未来,即)......我的意思是,只需在全球范围内安装包裹,你就像,只需一个命令即可在两秒钟内完成

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM