Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can we run sucrase in the browser like babel-standalone? #507

Open
alexilyaev opened this issue Feb 12, 2020 · 16 comments
Open

Can we run sucrase in the browser like babel-standalone? #507

alexilyaev opened this issue Feb 12, 2020 · 16 comments

Comments

@alexilyaev
Copy link

alexilyaev commented Feb 12, 2020

For the same reasons babel-standalone exists.
Would be nice to be able to run sucrase in browser code.

e.g.

<div id="root"></div>
<script src="https://unpkg.com/.../sucrase.js"></script>
<script type="text/sucrase" src="app.js"></script>

Right now babel-standalone doesn't support React Fragments (it's stuck on babel v7 beta 3).

@alangpierce
Copy link
Owner

Hey @alexilyaev , Sucrase itself runs fine in the browser (it doesn't have any node dependencies), though at the moment there's no pre-packaged browser build attaching it to the global scope, and there's no support for text/sucrase-style scripts.

In the past, I've been hesitant about a browser bundle the attaches Sucrase as a global since it's kind of the "old way" of using libraries, though the text/sucrase type of use case does seem compelling. In your case you'd just use the jsx transform, is that right? Seems like the typescript, flow, and imports transforms would only make sense in environments with additional tooling where you might as well have webpack (or similar) set up, though I could see a use case for TS/Flow checking and still wanting the script directly loaded to the browser rather than through webpack.

@alexilyaev
Copy link
Author

Well, my use case is teaching React with no bundler, currently it looks like this:

<div id="root"></div>

<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.js"></script>

<script type="text/babel" src="app.js"></script>
// app.js
const App = () => {
  return <h1>Hello World!</h1>;
};

ReactDOM.render(<App />, document.querySelector('#root'));

So React is global.
import and require don't work in this context.
TypeScript would have been a nice addition as it useful for teaching.

Right now I'm only missing the React Fragment <>...</> syntax support, which was added in babel-standalone v7.0.0-beta.31...

EDIT:

I was using an old package of babel-standalone, the new one has the latest versions:
https://unpkg.com/browse/@babel/[email protected]/

So this one does support the React Fragment syntax (and TS as well).

<script src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>

But, that file weighs 1.6 MB.
So, if sucrase could do it leaner, I'd be happy about that.

@tomByrer
Copy link
Contributor

tomByrer commented Feb 15, 2020

duplicate of #506

BTW @alexilyaev, once this happens, you can use jsDelivr CDN to use only 1 request. Try this out instead of all your 3 unpkg requests. though mine uses the current Babelv7.8.x & includes MaterialUI:

<script src="https://cdn.jsdelivr.net/combine/npm/[email protected]/umd/react.development.js,npm/[email protected]/umd/react-dom.development.js,npm/@material-ui/[email protected]/umd/material-ui.development.js,npm/@babel/[email protected]/babel.min.js" crossorigin="anonymous"></script>

Note my versioning: Patch releases are auto-updated, but the Minor versions are fixed.
Takes about 5 hits to your local POP before this concocted request is cached.
Details: https://www.jsdelivr.com/features

@alexilyaev
Copy link
Author

@tomByrer That looks very interesting, I'll check it out, thanks!

@tomByrer
Copy link
Contributor

@alangpierce Any extra consideration for a public standalone please? I'd love to use it via jsDelivr as I posted above.

@alexilyaev My link work for you? I've updated the versions successfully today.

@alexilyaev
Copy link
Author

@tomByrer Your link does work, nice one liner.

For the training I eventually downloaded the files via npm and linked to them in the example files.
Even managed to add MobX with Decorators support, which I was very happy about.
In that sense, Babel does provide quite a bit of flexibility.

<body>
  <div id="root"></div>
</body>

<script src="../../../../node_modules/react/umd/react.development.js"></script>
<script src="../../../../node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="../../../../node_modules/mobx/lib/mobx.umd.js"></script>
<script src="../../../../node_modules/mobx-react-lite/dist/index.js"></script>
<script src="../../../../node_modules/mobx-react/dist/mobxreact.umd.development.js"></script>
<script src="../../../../node_modules/@babel/standalone/babel.min.js"></script>
<script>
/**
 * This is only needed for this training course, to be able to write modern JS
 * without running a build/bundler.
 */

const Babel = window.Babel;

/**
 * Configure @babel/standalone transformations:
 * https://babeljs.io/docs/en/babel-standalone
 */
Babel.registerPreset('ai-react', {
  presets: [
    // Enable legacy decorators for MobX
    // https://babeljs.io/docs/en/babel-preset-stage-2
    [Babel.availablePresets['stage-2'], { decoratorsLegacy: true }],
    Babel.availablePresets.react
  ],
  plugins: [
    // Map package imports to their global namespaces
    // https://babeljs.io/docs/en/babel-plugin-transform-modules-umd
    [
      Babel.availablePlugins['transform-modules-umd'],
      {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM',
          'mobx-react': 'mobxReact',
          'mobx-react-lite': 'mobxReactLite'
        },
        exactGlobals: true
      }
    ]
  ]
});
</script>

<script
  type="text/babel"
  data-plugins=""
  data-presets="ai-react"
  src="app.js"
></script>

For my use case it's good enough.
But I can imagine some online editors wanting to use sucrase in the browser and babel being too big for them.

@osdevisnot
Copy link

@alexilyaev can you try importing from pika CDN?

import * as sucrase from 'https://cdn.pika.dev/sucrase'

@alexilyaev
Copy link
Author

@alexilyaev can you try importing from pika CDN?

import * as sucrase from 'https://cdn.pika.dev/sucrase'

I didn't understand how does that help me achieve what babel-standalone is doing?
Looking at my code example above, where would I fit that line?
And how would it map import React from 'react'; in my app.js?

Example app.js that needs to work in the browser:

import React from 'react';
import ReactDOM from 'react-dom';

const root = <button className="btn-primary">Click me!</button>;

ReactDOM.render(root, document.querySelector('#root'));

@nestarz
Copy link

nestarz commented Dec 24, 2020

Here an example on how you can setup sucrase to work in the browser using a service worker:
https://gist.github.com/nestarz/dcaa70b5ecac5fa7e66103658f7ff0b7

The caveat is that I copied paste the code (from skypack) of sucrase inside the sw.js.

@curran
Copy link

curran commented Jul 14, 2021

I would be interested in a browser build for Sucrase that introduces a global. My use case is a browser-based code editor. I have it up and running using Buble, but looking to migrate to Sucrase as Buble does not support optional chaining (and Buble has tons of unused stuff for transforming ES6).

Here's an example of where it would be used:

image

https://vizhub.com/curran/c3b14112dae34ef395999cef5783324f?edit=files&file=index.js

In the past, I've been hesitant about a browser bundle the attaches Sucrase as a global since it's kind of the "old way" of using libraries

Indeed, it's the "old way", but IMO it's fine. Lots of things still operate the "old way" with script tags and browser globals, and it's a tried and true approach. Also, what are the downsides of introducing a new dist file? Not many. It poses no risk of breakage.

@ClassicOldSong
Copy link

It'll be nice if Sucrase could include a UMD or IIFE version in release. Then we'll be able to use it directly via importScripts in Service Workers.

I'm writing an on-the-fly build tool using Service Worker, whose goal is to rid of node completely for modern frontend development/production, and I'm finding an alternative to esbuild since it could go out of stack strangely in Safari, but lacking of UMD/IIFE support won't make me able to create a plugin for Sucrase.

Currently there's only a CJS version and https://bundle.run/sucrase could do nothing about it.

@curran
Copy link

curran commented Dec 1, 2021

I agree.

It seems this work was done already here #526

That PR was closed in favor of using

import * as sucrase from 'https://cdn.pika.dev/[email protected]'

, but I think it would be great to include a browser build with the Sucrase package distribution directly, rather than introduce a dependency on a third party service/CDN.

@ClassicOldSong
Copy link

What's making things worse is that these CDNs are all serving only ESM, while import in Service Workers still require quite modern Chrome to be functional.

@curran
Copy link

curran commented Dec 7, 2021

I'm proposing that a UMD build be created for use over CDNs, not the ESM build.

@altbdoor
Copy link

For what its worth, I tried building sucrase with Rollup and IIFE in https://github.com/altbdoor/sucrase-build-iife#usage

I mostly followed the existing work in #526 , with minor adjustments to make things work. I managed to get things work in a service worker, to compile JSX to JS.

@curran
Copy link

curran commented Oct 31, 2023

Very nice! I could imagine this going into mainline Sucrase as an additional npm script that runs on prepublish:

          npx rollup -i ./package/dist/index.js \
            -f iife \
            -n sucrase \
            --banner "/* sucrase v$VERSION */" \
            -p '@rollup/plugin-node-resolve' \
            -p '@rollup/plugin-commonjs' \
            -p '@rollup/plugin-terser' \
            -o dist/sucrase.browser.js

From your work in https://github.com/altbdoor/sucrase-build-iife/blob/master/.github/workflows/build.yml#L79C1-L86C39

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants