I am trying to use tone.js on ESM modules. (I could use it without problems in “commonjs” with a bundler)
In the html I have
<script src="tests.js" type="module"></script>
and tests.js:
import * as Tone from "./Tone.js"
gives -> Tone.Gain is not a constructor
If I try:
import * as Tone from "./node_modules/tone/build/esm/index.js";
then Chrome shows status 404 Global not found, and the same for classes, version, ToneAudioBuffer, AudioContext, ToneAudioBuffers andToneBufferSource
(Maybe I am wrong, just starting with ESM modules, but digging into that esm/index.js the imports are like
import { ToneAudioBuffer } from "./core/context/ToneAudioBuffer"; (without .js extension, shouldn’t have any ESM module explicitly add the extension?)
I’ve lost track of other combinations I have tried without success and I can not find a working example of a such project.
What would be the right way - if possible- to run Tone.js on js modules?
Without bundling, serving a HTML with a module script, try import "./node_modules/tone/build/esm/index.js";.
Or use a build of some kind, then use the recommended import import * as Tone from "tone";.
Optionally, use the CDN, with the plain global <script src="https://unpkg.com/tone#14.7.77/build/Tone.js"></script> or the module syntax above.
<script type="module">
import "https://unpkg.com/tone#14.7.77/build/Tone.js";
const btn = document.querySelector("button");
btn.addEventListener("click", async () => {
await Tone.start();
const synth = new Tone.Synth().toDestination();
const now = Tone.now();
synth.triggerAttack("C4", now);
synth.triggerRelease(now + 50);
});
</script>
<button>Play</button>
Related
I am testing a React environment without a build process by loading React and Babel scripts directly from CDN.
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.
Since there is no babel config file how can I tell babel not to do this? In other words, how can I load React with script tags from CDN and still use ES6 modules?
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)
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).
Babel standalone added support for browser-native modules in v7.10.0 (including the data-type="module" attribute), while you're using v6. Removing the version number in the CDN or defining a specific one >= 7.10.0 fixes the transform-to-require issue.
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".
Secondly though, Babel won't transform the files that you import, so that JSX would be considered invalid. This leaves you with two options.
Create your own import function, and manually import like this (working example)
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);
okay, okay, WHY though wouldn't you use a bundler?? This is how the world works and always will (for the forseeable furture, i.e.)... I mean, just install parcel globally and you're like, done in two seconds with just a single command
I am trying to create a simple JS/ESM based Angular example. It has been a while since I have been in the angular space and I see there are really 2 options
Using the UMD lib (I would like to avoid this)
Use the ESM2015 folder and load using ESM (this is what I would like to do)
I try doing this like...
<html>
<head></head>
<body ng-app="jrg-module">
<jrg-element></jrg-element>
<jrg-app></jrg-app>
<script type="module">
import { Component } from "//unpkg.com/#angular/core/esm2015/index.js";
import { platformBrowserDynamic } from "//unpkg.com/#angular/platform-browser-dynamic/esm2015/index.js"
import {ShadowElement, CREATE_ELEMENT} from "//unpkg.com/#jrg/ui/target/jrg-ui.esm.mjs";
class JrgElement extends ShadowElement {
constructor() {
super("<h1>CustomElement</h1>");
this.render();
}
}
CREATE_ELEMENT("jrg-element", JrgElement, {});
const MyComponent = Component({
selector:"jrg-app",
template:"<h1>Angular</h1>"
}).Class({
constructor: function() {}
});
const app = platformBrowserDynamic().bootstrapModule(MyComponent)
</script>
</body>
</html>
But (after taking forever to download 500+ files) I get
Uncaught TypeError: Error resolving module specifier “rxjs”. Relative module specifiers must start with “./”, “../” or “/”.
Can I use the ESM version in the browser or do I have to use UMD? If I can use ESM from the browser is there a link to an example?
I swear Angular used to have a dropdown for their examples where you could switch between TS and JS but I don't see it now.
Have you tried out the website stackblitz it has plenty of angular examples of setting up a new project.
You can also do ng new my-app from the cli to generate a new project locally.
Angular has moved away from javascript in favor of typescript, so you will have to use ESM
We are trying a POC of adding Typescript and Webpack to our Angularjs project.
I am able to get my webpack bundle to generate, however at runtime the program cannot find the various functions in my validator.js. Can you please offer some advice?
login-view.components.ts
declare var findFormNode: any; //function in validator.js
//LogInUser
self.login = function ($event, command) {
if (findFormNode($event.target.id)) {
...
}
}
main.ts is importing the file
import "./../../../CommonStaticFiles/include/js/Validators.js";
bundle.js
eval("/* WEBPACK VAR INJECTION */(function($) {/*\r\n\r\n VALIDATORS\r\n\r\n ... n\n\nfunction findFormNode(
error
ReferenceError: findFormNode is not defined
at LoginController.self.login (login-view.component.ts:28)
at fn (eval at compile (angular.js:NaN), <anonymous>:4:267)
at callback (angular.js:29019)
In order for your functions to be properly imported, there are few things that you have to make sure of.
First, make sure you are exporting your functions correctly. Here's an example of how to export a function from Validator.js:
export const validateFunc1 = ():void => {};
Next, you have to make sure you are using proper import syntax. In order to import the function above, you would do the following:
import {validateFunc1} from "./../../../CommonStaticFiles/include/js/Validators.js";
Alternatively, if you want to import all exported functions at once, then you can use this syntax:
import * as validatorFuncs from "./../../../CommonStaticFiles/include/js/Validators.js";
Lastly, check that the location of Validators.js is correct. It's a common mistake to be looking in the wrong directory. Your code editor can usually help you find the right path to use.
Is it not possible to access already 'built' components within the html file that the build is linked to?
I am trying the following -
In bundle.js
var React = require('react');
var ReactDOM = require('react-dom');
var Titles = React.createClass({
render() {
return (
<div>
<h1>{this.props.headerProp}</h1>
<h2>{this.props.contentProp}</h2>
</div>
);
}
});
In my html page -
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
<div id="con"></div>
<script type="text/javascript" src="/public/bundle.js'"></script>
<script type="text/jsx">
ReactDOM.render(<Titles headerProp = "Header from props..." contentProp = "Content
from props..."/>, document.getElementById('con'));
</script>
But console outputs React is not defined.
I have even tried to set react globally within the bundle -
window.React = React;
And calling it with window. prefixed but yields the same result.
Because you're mentiong a bundle.js file with a snippet containing commonjs style imports, I'm assuming you're using Webpack.
I have some considerations about your code.
bundle.js file will not expose any module as global. That includes React and any other module you might require inside the bundle. There isn't goint to be window.ModuleName. However, these module are accessible in the Browser via require.js because Webpack will export modules as UMD, that is, they will be accessible through either commonjs or AMD (Require.js).
I'm pretty sure that, if in the entry point of your webpack configuration file, you do something like var React = require("react"); window.React = React, that's actually going to work.
There's a Webpack module meant to expose modules globally (like in window.x) in a more ellegant way than (2) called expose-loader. You should take a look at it.
You should really try to avoid doing what you're trying to do. In your entry.js file (the entry point of your webpack configuration) should be responsible for doing something like ReactDOM.render(..., document.getElementById("#app")). So that, just by including your bundle, the app will render automatically. This is what everybody does.
JSXTransformer.js as well as the <script type="text/jsx"> have been deprecated a long time ago. Now you're supposed to use Babel to compile React.
To learn the new ES6 syntax, I've been trying to refactor some JS code.
I'm absolutely confused though by the whole import / export methods.
How do I change this require statement into ES6?
var remote = require('electron').remote
I've seen this answer but:
It doesn't work
It doesn't really seems to be much ES6-sque
Any thoughts?
It seems imports are not implemented in either Node 6 or Chrome 51 so Electron also does not support them, according to this post: https://discuss.atom.io/t/does-electron-support-es6/19366/18
And also the last electron doc doesn't use imports, they use destructuring syntax:
const { BrowserWindow } = require('electron').remote
// or
const { remote } = require('electron')
const { BrowserWindow } = remote
http://electron.atom.io/docs/api/remote/
But you can use babel with the require hook:
http://babeljs.io/docs/usage/require/
To be auto compile each required modules so you will be able to use imports.
Of course the script given to electron (the one that require babel) is not compiled so you need to make a bootstrap:
// bootwithbabel.js
require("babel-register");
require( process.argv.splice(2) );
In shell (sh):
electron bootwithbabel.js app.es
alias electrones="electron bootwithbabel.js "
electrones coron.es // ^^
Then in your app you can then write:
import electron from 'electron';
import { remote } from 'electron';
You can also import only the remote module:
import { remote } from 'electron';
But you can only import both in one statement:
import electron, { remote } from 'electron'
electron.ipcRenderer.on();
let win = new remote.BrowserWindow({width: 800, height: 600});
remote.getGlobal(name)
playground
I'm absolutely confused though by the whole import / export methods.
Mixing different module systems can indeed be confusing.
It doesn't work
const electron = require('electron');
const remote = electron.remote;
is exactly the same as what you have
var remote = require('electron').remote
If yours work, the other will as well. However, I would simply stick with yours.
It doesn't really seems to be much ES6-sque
Who cares? Node doesn't support ES6 imports and exports natively and it's not super clear how CommonJS modules should map to ES6 modules. I recommend to stick with require if you are only writing for Node anyway.
You could try to do
import electron from 'electron';
const {remote} = electron;
These days every version of Electron comes with basic typescript support. So if you use a TS or TSX file in your project -then you can use ES Import statements inside that file. Whether you use an ES module or not.
https://www.electronjs.org/blog/typescript