Difference between ES2015 `import * as` vs just plain `import` - import

I just fixed a bug by changing import * as CodeMirror to just plain import CodeMirror.
I copied this code. (Porting it from TypeScript)
import * as CodeMirror worked until an addon was imported for its side effects: the expected new fold property was undefined.
Questions: (I am trying to understand what happened better)
What is going on? How did this change fix the bug?
Who is adding the default property to CodeMirror? (Or more likely: wrapping the module inside another object that looks very similar) The most likely suspects:
JavaScript modules (ES2015)
Babel
Webpack
CoffeeScript
CodeMirror
Is there a better way to accomplish what I was trying to achieve?
More details:
This code doesn't work as expected:
import * as CodeMirror from 'codemirror'
import 'codemirror/addon/fold/indent-fold.js' # should add `fold` object to `CodeMirror`
console.log typeof CodeMirror ## 'object'
console.log typeof CodeMirror.fold ## 'undefined'
console.log typeof CodeMirror.default ## 'function'
## Work-around:
console.log typeof CodeMirror.default.fold ## 'object'
This code works as expected:
import CodeMirror from 'codemirror'
import 'codemirror/addon/fold/indent-fold.js' # should add `fold` object to `CodeMirror`
console.log typeof CodeMirror ## 'function'
console.log typeof CodeMirror.fold ## 'object'
console.log typeof CodeMirror.default ## 'undefined'
I have already studied these resources, but they have not helped me fully understand what happened:
JS import reference
JS export reference
CoffeeScript modules

Let's assume you have a very simple module named 'test-module', in it you have:
var test = 'test';
export default test;
export function helloWorld () { ... };
When you do:
import something from 'test-module';
you are only importing the default export of 'some-module'. In this case, it is the string test. The default export can be anything, object, function, etc.
When you do:
import {helloWorld} from 'test-module';
You are specifically importing a member of 'test-module' named 'helloWorld' and not the default export. In this case, it is the function 'helloWorld'.
If you had done:
import {something} from 'test-module';
The 'something' would be 'undefined' since there is no export for with that name.
import * as something from 'test-module';
is asking for an object with all of the named exports of 'test-module'.
Then you can access any of the exports in 'test-module' as something.name. In this case they will be something.default and something.helloWorld.

import * as CodeMirror from 'codemirror' imports all the named exports and namespaces them into an object called CodeMirror.
import CodeMirror from 'codemirror' imports the default export.

Related

How to dynamically import a json file

I'm trying to import a JSON file on my Vite app, whose paths are dynamically generated. So the import path for this JSON includes variables.
I know it's possible to do it with require, but I'm working with Svelte, and I cant use requires.
You can use a dynamic import() statement for that. This will return a promise, which has to be awaited, though. E.g.
<script lang="ts">
import meta from './meta.json';
const filePromise = import(/* #vite-ignore */ `./${meta.file}.json`);
</script>
{#await filePromise then file}
{file.property}
{/await}
There are some limitations to dynamic imports in Vite so the application can be built properly. The #vite-ignore comment silences a warning output about these limitations.

Luxon not running in stackblitz with typescript

I'm trying to make a luxon example in stackblitz, but the imports are not working.
The luxon library and its types are added, and it is imported at the beginning of the file:
However I get the message that it is undefined!
I tried to find other examples of stackblitz (google: "luxon stackblitz") however none of them seem to work or use and old version, which is imported via CDN
Do I somehow have to add the whole luxon library to the project?
Code (super simple)
// Import stylesheets
import './style.css';
import { DateTime } from 'luxon';
// Write TypeScript code!
const appDiv: HTMLElement = document.getElementById('app');
appDiv.innerHTML = `luxon sample -->"${DateTime.now()}"<--`;

How to type hint class definition

Consider the following example of 3 javascript files:
/** myclass.js **/
import jQuery from 'jQuery';
class MyClass {
constructor() {
this.property = null;
jQuery('#test').data('myClass', this);
}
testMethod() {
return null;
}
}
export default MyClass;
/** file.js **/
import MyClass from './myclass.js';
new MyClass();
export default null;
/** index.js **/
import './file.js';
import jQuery from 'jQuery';
let myValue = jQuery('#test').data('myClass');
What I would like to achieve, is to get property and method auto suggestion from my IDE on the myValue variable. I know (I mean I presume) that automatically, there is no way for the IDE to know what I stored in the data variable of jQuery, but what kind of type hint should I provide before myValue to tell the IDE, that it should be an instance of MyClass?
If in index.js I also import myclass.js with the definition of the class, I was able to achieve my result, by type hinting before the variable with the following jsdoc comment:
/** #type {MyClass} */
But this line only works if I also imported the definition in the current scope. Is there any way to either:
achieve suggestions automatically, without manually type hinting?
or if that is not possible, type hint, without manually importing the definition beforehand?
I am using Visual Studio Code v1.46.1 and I have the ESLint v2.1.5 extension installed on it.
EDIT: After trying to create a jsconfig.json file in my root folder, with the following options:
{
"exclude": ["node_modules"]
}
and modifying my index.js by adding this jsdoc comment, I am still getting no autosuggestions by VSCode:
/** #type {MyClass} */
I've tried adding the above comment both above, and below the line, where I fetch the data from the jQuery element.
EDIT 2:
Okay, basically, it looks like that my IntelliSense "breaks" when I am trying to export something from a file. Could this be a VSCode issue?

Three.js - How to convert import methods into regular js files

On this fiddle https://jsfiddle.net/k2c5upfo/1/, extern modules are called using the import method. I don't use node on my project. I'd like to convert all these import files into regular javascript files. How can I built them without using node.js ?
import * as THREE from "https://cdn.jsdelivr.net/npm/three#0.118.2/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/controls/OrbitControls.js";
import { EffectComposer } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/postprocessing/EffectComposer.js';
import { ShaderPass } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/postprocessing/ShaderPass.js';
import { RenderPass } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/postprocessing/RenderPass.js';
import { ClearPass } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/postprocessing/ClearPass.js';
import { MaskPass, ClearMaskPass } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/postprocessing/MaskPass.js';
import { CopyShader } from 'https://cdn.jsdelivr.net/npm/three#0.118.2/examples/jsm/shaders/CopyShader.js';
For example, I was able to call 'OrbitControls.js' on a older version of three.js by simply add another file. Can I still use this method ? Thank you
EDIT :
I managed to convert my workflow using es6 modules. I've been wondering if there's a way to only import specific modules. My generated output file has the same weight with theses two different lines.
import {Scene, PerspectiveCamera, WebGLRenderer, CylinderBufferGeometry, MeshNormalMaterial, Mesh} from "../node_modules/three/build/three.module.js";
import * THREE from "../node_modules/three/build/three.module.js";
Is there a way to only have the part of code that I need in my final output ? Thank you.
Using global scripts is actually deprecate since r117. At the end of the year, using ES6 modules is the only way of importing example files.
I don't use node on my project.
Not sure I understand this sentence. The above fiddle is unrelated to node.js. You can import ES6 modules directly in HTML files as long as you put the import statements into script tags that look like so:
<script type="module">
</script>
This approach is also used by the official examples.

I couldn't import/require react-component class inside a node_modules package on web development

my code is like:
import Render from './AppeRender';
import { Component } from 'react';
export default class appDB extends Component {
render () {
return Render.call(this, this.props, this.state);
}
}
and what i'm getting is:
Module parse failed: /home/projects/node_modules/DB/Db.js Line 5: Unexpected token
You may need an appropriate loader to handle this file type.
Note: Error only comes in web setup, it's working fine in android and in IOS i haven't tried yet.
Does anyone have any idea regarding this.
I think what is wrong here is that you using import twice (and the second one is a destructure.
Try this instead:
import { Component } from 'react';
import Render from './AppeRender';
You can bind Component in one import.
The second import could have been changed to a straight destructure:
const { Component } = React;
But, there is no reason to do this if you are only using Component.
Using import on an Object is not really correct (however, it might work with some implementations), I assume that is why the error was occurring.