(How) can I use System.import in babel along with require.js? - babeljs

I'm playing a little bit with the new ES6 functionalities and Babel. I'm successfully using the modules export/import functionalities by means of require.js (transpiling into AMD), but the experimental module loader doesn't want to work. Here is my code and configurations:
extract of front-app/tst.js
import {tstimp as functocall} from "front-app/tstimp.js";
...
/**
* LOADING MODULES DYNAMICALLY
*/
System.import('front-app/tst_dyn_mod')
.then(some_module => {
console('using the module!');
some_module.sayHello();
})
.catch(error => {
console.log('error!');
console.log(error);
});
My .babelrc looks like this:
{
"presets": ["es2015", "react"],
"plugins": ["transform-es2015-modules-amd"]
}
and the scripts I import are these ones, in that order:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
<script data-main="front-app/tst" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.8/require.min.js"></script>
<script src="node_modules/es6-module-loader/dist/es6-module-loader.js"></script>
</head>
<body></body>
</html>
Unfortunately what I get is the following error by using firefox:
error! tst.js:695:9
Error: a is undefined
Error loading http://localhost/es6r1/front-app/tst_dyn_mod
what's that a? Am I missing something? Keep in mind my code is transpiled into AMD, but System is supposed to stay there in the transpiled code (and it IS there). The polyfill should do the dirty job, right?

I successfully get the thing working on Babel 6 with a slighlty different config (babel-node cli & thus commonjs) thanks to this plugin: https://www.npmjs.com/package/babel-plugin-system-import (npm install babel-plugin-system-import-transformer). Here's a excerpt of my .babelrc:
…
"plugins": [
"system-import-transformer",
{
"modules": "common"
}
]
…
Setting amd instead of common like indicated in the documentation should do the trick for you.
Only limitation of this tiny plugin, you should get a plain string module name like System.import("plainString") and not a computed one (nor string concatenation with +, nor new ES6 template literal and neither variable name). It seemds linked to that line of code.
I will try to PR a fix on that limitation if I can.

Just an update on this, https://github.com/thgreasi/babel-plugin-system-import-transformer has support for non string parameters. Just make sure not to use the updated alias package.

Related

Specifying window (global) variable type hinting in VSCode from external JS file without typescript

This may be a silly question but I really don't know where to look.
I'm creating a browser testing environment for a pretty large-scale API written in typescript. This API uses esbuild to build the typescript files into a /dist/ folder with a single index.js entry-point and its appropriate d.ts file.
I've created a /tests/ folder to hold some browser files that includes an index.html file with Mocha and Chai imported. It also imports /dist/index.js which is set globally to a window.myAPI variable.
In /tests/index.html:
import * as myAPI from "./dist/index.js"
Alongside index.html in the tests folder, there are separate JS files included for different tests that run things on window.myAPI... to do assertion tests.
search.test.js
book.test.js
navigate.test.js
I then run a server to host at the root. These separate tests are then imported from /tests/index.html. The separate tests look like this inside:
const { chai, mocha } = window;
const { assert } = chai;
describe("Search", function() {
describe("Setup", function() {
it("Setting URL should work", function() {
const call = myAPI.someCall()
assert.ok(call);
});
});
});
mocha.run();
Everything works, but I have no code hinting for myAPI. I'd like to be able to see what functions are available when I type myAPI, and what parameters they take, and what they should return - along with all my comments on each function.
In typescript you can do things like ambient declarations, but I don't want to make my tests typescript because then I add an unnecessary build step to the tests. But it would be as easy as:
/// <reference path = "/dist/index.d.ts" />
How can I tell VSCode that window.myAPI is an import of /dist/index.js and should import the types as well so I can see them ?
I'm open to different solutions to this, but I feel like this should be pretty simple. I don't know if ESLint is capable of doing something like this, but I tagged it because I feel it's relevant.
Thanks!

How to use stage 3 syntax in svelte/sapper?

I want to use class property and private fields in my sapper project. Apparently they have to be preprocessed by babel right now.
I tried to add the corresponding babel plugins to rollup.config.js, only to realize a few things.
the babel rollup plugin is only used in legacy mode.
the server part doesn't use babel at all.
I tried to add the babel rollup plugin to the end of server plugins like this,
babel({
extensions: ['.js', '.mjs', '.html', '.svelte'],
runtimeHelpers: true,
exclude: ['node_modules/#babel/**'],
plugins: [
'#babel/plugin-proposal-class-properties',
'#babel/plugin-proposal-private-methods',
],
}),
But it doesn't seem to take effect at all.
I also added it to the client plugins (before the legacy entry), but it complained about I needed to add #babel/plugin-syntax-dynamic-import, so looks like babel has to recognize the whole syntax in order to preprocess, and I don't really want to compile dynamic import for modern browsers.
How do I enable the use of esnext syntax in sapper?
You would need to preprocess the contents of <script>, using the preprocess option in rollup-plugin-svelte:
plugins: [
svelte({
// ...
preprocess: {
script: ({ content }) => {
return transformWithBabel(content);
}
},
// ...
})
]
In an ideal world we'd have a ready-made preprocessor plugin for doing this; as it is, the transformWithBabel function is left as an exercise to the reader for now. Essentially it would involve import * as babel from '#babel/core' and using the Babel API directly, which I guarantee will be lots of fun.
Note that #babel/plugin-syntax-dynamic-import doesn't compile dynamic import, it only allows Babel to parse it. Without it, Babel can't generate a valid AST from the code inside <script>.

react-jsonschema-form How to use it via cdn?

I am trying to use this library "react-jsonschema-form" to create forms using react and jsonschema.
I am trying to use it in my project as described in the example from the website by including the .js file via cdn. It is not working. The exported component "Form" is undefined.
I had a look at this similar question Using React component from js source maps but I could not understand the solution offered. I am supposed to alias the default export of JSONSchemaForm. But what is JSONSchemaForm? and where can I find it? Is it another library to be included?
Here is what I tried to do:
Using Require.js I have imported the cdn library:
var require = {
baseUrl: "/js/",
waitSeconds: 600,
paths: {
'react-forms': ['https://unpkg.com/react-jsonschema-form/dist/react-jsonschema-form']
},
}
Then in my code I import the library:
var rf = require('react-forms')
But now when I access Form (rf.Form), it is undefined. I had a look at the "react-jsonschema-form.js" source code. "Form" is defined no where.
From the instructions of the library page it is said:
You'll also need to alias the default export property to use the Form component:
const Form = JSONSchemaForm.default;
// or
const {default: Form} = JSONSchemaForm;
But JSONSchemaForm is also undefined.
So I don't know what I am doing wrong. How can I use "react-jsonschema-form" library by including it as a script tag?
Thank you community.
1. Include the cdn path
<script src="https://cdn.jsdelivr.net/npm/react-jsonschema-form#1.0.3/dist/react-jsonschema-form.js"></script>
2.By using field get the access of jsonformDefaultValues;
` <script type="text/babel"
const fields = JSONSchemaForm.default
return(
<Form
schema={schema}
uiSchema={uiSchema}
field={fields}
onSubmit={onSubmit}
</Form>)
</script>`
I was able to solve this problem and I am reporting here the solution for any one facing a simlilar issue. To use react-jsonschema-form via cdn script tag (with require.js):
include this library via require.js by indicating the url path :
paths: {
'react-forms': ['https://unpkg.com/react-jsonschema-form/dist/react-jsonschema-form']
}
include this polyfill library: cdn.polyfill.io/v2/polyfill.min.js
Make sure to use the latest react version ( version v15)
In you code, require the library and alias its default export like this:
var rf = require("react-forms");
const Form = rf.default;
(This is because I am using require.js module system. For another module system, you may use JSONSchemaForm.default)

How does SystemJS support multiple versions of the same library?

I'm working on a jspm/systemjs app and would like to better understand how SystemJS handles multiple versions of the same dependency. Consider the following (simplified) SystemJS config example:
map: {
"react": "npm:react#0.14.8"
"npm:foo": {
"react": "npm:react#0.14.7"
}
}
I assumed when my code imported react it would get v0.14.8, while code in the "foo" dependency would receive v0.14.7. However, my browser console prints warnings about multiple copies of react being found.
Questions:
How does SystemJS supports multiple versions of dependencies,
Why would I be receiving an error like this if the different versions are kept separate?
Since SystemJS uses import-maps, you can use this approach:
Using Multiple Versions of the Same Module
It's easy to require multiple versions of the same package with import maps. All you need to do is use a different import specifier in the mapping as shown below:
<script type="importmap">
{
"imports": {
"lodash#3/": "https://unpkg.com/lodash-es#3.10.1/",
"lodash#4/": "https://unpkg.com/lodash-es#4.17.21/"
}
}
</script>
You can also use the same import specifier to refer to different versions of the same package through the use of scopes. This allows you to change the meaning of an import specifier within a given scope.
<script type="importmap">
{
"imports": {
"lodash/": "https://unpkg.com/lodash-es#4.17.21/"
},
"scopes": {
"/static/js": {
"lodash/": "https://unpkg.com/lodash-es#3.10.1/"
}
}
}
</script>
With this mapping, any modules in the /static/js path will use the https://unpkg.com/lodash-es#3.10.1/ URL when referring to the lodash/ specifier in an import statement, while other modules will use https://unpkg.com/lodash-es#4.17.21/.
Source: https://www.honeybadger.io/blog/import-maps/

Typescript import class

I have been trying to get this thing to work for quite a while now, and so far no solution that I have found has worked for me.
This is what I have:
//Test.ts
module t
{
export class Test
{
constructor ()
{
alert("test");
}
}
}
//Main.ts
/// <reference path="Test.ts" />
var test: t.Test = new t.Test();
As you can see I have two files, one is Main.ts and the other one is Test.ts. They are both in the same folder. Also if it helps I am using VS2012 and the Typescript plugin.
Thank you for the help!
EDIT: Oh btw, I get the error (in chrome): Uncaught ReferenceError: t is not defined
You need to include both scripts in your web page:
<script src="test.js"></script>
<script stc="main.js"></script>