Can I use ES modules in browser with babel, without bundling my code?

Viewed 1262

I'd like to load my reactjs code in the browser using babel-standalone. So I'm looking for the correct configuration for babel standalone (or any other solution) in order to load ES modules in the browser while using babel.

I created the Glitch below to show my problem. https://glitch.com/edit/#!/example-es-modules-with-babel?path=index.html:1:0

Edit: Above link now contains a working example.

I spent a fair amount of time looking and trying things out, but it seems quite difficult to figure out this on my own. So I'm wondering if someone could help me to get above Glitch working.

For a similar issue discusstion please see: https://github.com/babel/babel/issues/9976

Edit: Motivation

This is just for fun and for prototyping ideas like in a codepen. Creating a dev setup and bundling the js code is the best thing for any non-trivial app.

1 Answers

I got it to work with your code by making a few changes. Here is the glitch link. I'm putting both your original code and the modified version at the bottom of this post - good idea to include code with your SO question in case glitch ever goes down or your project gets deleted.

Changes:

  • Switched from AMD to UMD. AMD uses require.js, which seems to conflict with babel-standalone as far as transpiling goes. Also removed the require.js script as part of that process.
  • Explicitly imported app.js with a script tag:
    • <script type="text/babel" src="./app.js" data-plugins="transform-modules-umd"></script>
    • If you want to switch to inline modules, you will need to use the data-module attribute. See this change to babel-standalone.

Also, please note that you are going down a route that you probably don't want. At the point where you are dealing with export/imports/modules and multiple component files, you really should switch to a bundler like webpack - there is a reason why most threads about this issue just recommend switching to it.


Original HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello!</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- import the webpage's stylesheet -->
    <link rel="stylesheet" href="/style.css">


    <script src="https://unpkg.com/@babel/standalone@7.4.4/babel.js"></script>    
    <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script>

    <script>
      Babel.registerPreset("my-preset", {
        presets: [
          [Babel.availablePresets["es2015"], { "modules": false }],
          [Babel.availablePresets["react"]]

        ],
        plugins: [
          [Babel.availablePlugins["transform-modules-amd"]]
        ],
        moduleId: "main"
      });
    </script>
    <script type="text/babel" data-presets="my-preset">
      import App from './app.js'
      ReactDOM.render(<App />, document.getElementById('root'));
    </script>

  </head>  
  <body>
    <p>Output should appear below.</p>
    <hr/>
    <div id="root"></div>
  </body>
</html>

Modified HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello!</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- import the webpage's stylesheet -->
    <link rel="stylesheet" href="/style.css">


    <script src="https://unpkg.com/@babel/standalone@7.4.4/babel.js"></script>    
    <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<!--     <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script> -->

    <script>
      Babel.registerPreset("my-preset", {
        presets: [
          [Babel.availablePresets["es2015"], { "modules": false }],
          [Babel.availablePresets["react"]]

        ],
        plugins: [
          [Babel.availablePlugins["transform-modules-umd"]]
        ],
        moduleId: "main"
      });
    </script>
    <script type="text/babel" src="./app.js" data-plugins="transform-modules-umd"></script>
    <script type="text/babel" data-presets="my-preset">
      import App from './app'
      ReactDOM.render(<App />, document.getElementById('root'));
    </script>

  </head>  
  <body>
    <p>Output should appear below.</p>
    <hr/>
    <div id="root"></div>
  </body>
</html>

And app.js stays the same:

export default () => <h1>It Works!</h1>
Related