Importing web component without module bundler - javascript

I am trying to follow these instructions for using web components. I installed the polymer paper-button with npm install --save #polymer/paper-button, addded the below to my index.html and opened it with vscode's live-server. But I get a console error saying: Uncaught TypeError: Failed to resolve module specifier "#polymer/iron-flex-layout/iron-flex-layout.js". Relative references must start with either "/", "./", or "../".. I would like to solve this without using a module bundler like webpack.
<script type="module" src="node_modules/#polymer/paper-button/paper-button.js"></script>
...
<paper-button raised class="indigo">raised</paper-button>

A workaround I have found is to instead use https://unpkg.com/ as per below:
<script type="module" src="https://unpkg.com/#material/mwc-button#latest/mwc-button.js?module"></script>
Note: you need to add the ?module parameter to the end of the URL in order for unpkg to fix the bare module syntax within the file requested otherwise it just returns the original file with bare module imports.

The error you're getting refers to the inability of browsers - even those that support ES modules - to resolve bare module imports (import foo from 'bar';).
Yes, here:
↓
<script type="module" src="node_modules/#polymer/paper-button/paper-button.js"></script>
you're importing by relative path but paper-button in turn is importing other modules by bare specifier:
paper-button.js:11:1
import '#polymer/iron-flex-layout/iron-flex-layout.js';
To know more about modules in the browser and the reasons behind the lack of support for bare specifiers I would recommend this article by Damien Seguin.
You don't necessarily need a module bundler to be able to launch the application: polymer serve, Polymer's dev server, resolves module specifiers automatically. Also, Polymer CLI's build command may be of help if you don't want to manually configure a build system or alternatively tools like Babel can help you transform imports without bundling.

Related

"Error resolving module specifier" danfojs

I was able to use danfojs using
<script src="https://cdn.jsdelivr.net/npm/danfojs#1.1.2/lib/bundle.min.js"></script>
However, the .js file is too big (over 6MB) for production so I need some help with dead code elimination.
I read that webpack's tree-shaking is good for eliminating dead code
I therefore "npm install danfojs" per the official documentation.
In my html file, I tried to do a ES6 import
<script type="module">
import * as dfd from 'danfojs';
import { readCSV, DataFrame } from 'danfojs';
</script>
In Firefox, when I load the webpage, it throws an error of
Uncaught TypeError: Error resolving module specifier “danfojs”. Relative module specifiers must start with “./”, “../” or “/”.
Any help getting the import running OR doing dead code elimination in another way would be much appreciated.
The folder structure is like this, based on a flask project
root
node_modules
danfojs
app
templates
home
webpage.html

cannot use import statement outside a module on built exe with electron-forge

I am creating an app with Electron and Vue (using js not ts).
When I run the app using npm run electron:serve the app runs fine.
I now want to build a Windows exe so I can distribute my app. I have tried using electron-builder, electron-packager and electron-forge. Whenever I can get the build to finish, running the exe throws the cannot use import statement outside a module error (referring to the first import statement it finds, i.e. import { app, protocol, BrowserWindow } from 'electron').
I've tried adding "type":"module" to my package.json but (due a bug in Vue, according to this question), that throws Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]
I've also tried changing all my import statements to require but this doesn't work because some of the node modules I'm using use import and the error just throws for those instead.
I'm tearing my hair out over this. Where do I go from here?
UPDATE:
I have found a workaround for the Vue bug and posted my findings on the linked question. I can now add "type":"module" to my package.json.
However, I now get an error thrown when I run npm run electron:serve and from my built exe:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: <my_project_root>\dist_electron\index.js
require() of ES modules is not supported.
require() of <my_project_root>\dist_electron\index.js from <my_project_root>\node_modules\electron\dist\resources\default_app.asar\main.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
To be clear, I'm not using require in any of my source code, but the compiled(?) version does?
What's going on here?
UPDATE 2:
As requested, here is a minimal reproducible example that maintains original folder structure, configs and package.json

Import from node_modules not recognized in es6 modules in browser

I'm trying to use lodash in my web application. I have installed lodash using npm in my local project.
I plan on using the ES6 modules in my code.
Here is my main.js file:
import * as _ from "lodash";
_.each([1, 2, 3, 4], (i) => {
console.log('index each ' + i);
});
And I have included it in index.html as:
<script src="js/main.js", type="module"></script>
But I get the following error in the browser console.
Uncaught TypeError: Failed to resolve module specifier "lodash".
Relative references must start with either "/", "./", or "../".
Note: I do not wish to use any bundling tool.
If you don't wish to use any bundling tools, you will need to provide a path to the lodash folder within node_modules, relative to the JavaScript file that you have the import statement in.
If you do not wish to use a bundler, it would also be worthwhile importing from the specific file, the function you need. For example:
import _each from '../node_modules/lodash/each'
As of 2021, please consider the following statement by Márton Salomváry (Jan 2018):
Unfortunately even most libraries authored or published in ES6 module format will not work because they target transpilers and rely on the Node.js ecosystem. Why is that a problem? Using bare module paths like import _ from 'lodash' is currently invalid, browsers don’t know what to do with them.
And also the statement by Jake Archibald (May 2017):
"Bare" import specifiers aren't currently supported.
Valid module specifiers must match one of the following:
A full non-relative URL.
Starts with /.
Starts with ./.
Starts with ../.
And javascript.info:
In the browser, import must get either a relative or absolute URL. Modules without any path are called “bare” modules. Such modules are not allowed in import.
Certain environments, like Node.js or bundle tools allow bare modules, without any path, as they have their own ways for finding modules and hooks to fine-tune them. But browsers do not support bare modules yet.
Bundlers facilitate the use of "Bare Imports" which is not supported by the browser yet. Unless you bundle your code, I recommend using the solution proposed by #Asler. Besides, a lot of work is currently being done to study the implementation of "Bare Imports" in the browser, please follow this link if you want to monitor the overall progress.
Eventually you can't use JS modules on browser like that. These modules are for webpack or other bundler.
Try module lodash-es
import each from '../node_modules/lodash-es/each.js'
If you are trying to import css file, make sure to mention .css in import statement.
you can add your node_modules to the public dirs, so you can easily shorten your importing syntax from ../../../../node_modules/my-package into /my-package
also, you need to specify the full path including the file and the extension
import mod from "/my-package/file.mjs"

How to use vaadin-text-field in script module

I have tried to use vaadin-text-field in a script module, but it fails with the following message
Uncaught TypeError: Failed to resolve module specifier "#vaadin/vaadin-lumo-styles/color.js". Relative references must start with either "/", "./", or "../".
Now I know that "Bare" import specifiers aren't supported in ES6
But is there a way to make this work without hacking on the component's imports.
I mean locally of course
Here is my code :
<!doctype html>
<html>
<head>
<!-- Polyfills only needed for Firefox and Edge. -->
<script src="node_modules/#webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
</head>
<body>
<script type="module">
import {PolymerElement, html} from './node_modules/#polymer/polymer/polymer-element.js';
import './node_modules/#vaadin/vaadin-text-field/theme/lumo/vaadin-text-field.js';
class MyElement extends PolymerElement {
static get properties() { return { }}
static get template() {
return html`
<vaadin-text-field></vaadin-text-field>
`;
}
}
customElements.define('my-element', MyElement);
</script>
<my-element></my-element>
</body>
</html>
Note: I am using server to serve the file not polymer CLI
I found that serving the file with polymer serve is the fastest way to solve the problem.
According to Polymer's Documentation
The browser accepts only one kind of module specifier in an import
statement: a URL, which must be either fully-qualified, or a path
starting with /, ./ or ../. This works fine for importing
application-specific elements and modules:
However, it's challenging when you're writing a reusable component,
and you want to import a peer dependency installed using npm. The path
may vary depending on how the components are installed. So Polymer
supports the use of Node-style named import specifiers
Where #polymer/polymer is the name of the npm package. (This style of
specifier is sometimes called a "bare module specifier".)
These module specifiers need to be transformed to paths before they're
served to the browser. The Polymer CLI can transform them at build
time, and the Polymer development server can transform them at
runtime, so you can test code without a build step. Many third-party
build tools, like WebPack and Rollup also support named modules.

Webpack importing video.js returns an empty object

I am trying to use video.js via webpack.
I installed video.js via npm - npm install video.js --save-dev
In webpack I read that video.js should be loaded via script loader else it throws an error.
This is how I am loading video.js through the babel loader
module:
loaders: [
{
test: /video\.js/,
loader: 'script'
}
]
I got this solution from here https://github.com/videojs/video.js/issues/2750
This is my import statement
import videojs from 'video.js';
The issue that I now face is the import is returning an empty object, so when I try to do this:
var vidTag = ReactDOM.findDOMNode(this.refs.html5Video);
this.videojs = videojs(vidTag);
I get this error:
renderer-0.js:8031 Uncaught (in promise) TypeError: (0 , _video2.default) is not a function(…)
Any help will be much appreciated. I am new to ES6 / React / Webpack
Please take a look at the loader's README before copy&pasting some random code. The script-loader is not appropiate here, because it imports scripts into the global scope while skipping the whole module system.
So, if you wanted to use the script-loader, you would just write:
import "script-loader!video.js";
console.log(videojs); // should be an object now
Usually I would not recommend the use of the script-loader because it neglects the whole point of a module system where you import stuff explicitly into the local scope. In the example above, the import happens as a side-effect into the global scope which is effectively the same as just using a <script> tag with all its downsides like name clashes, etc.
There are often better alternatives to it, like the exports-loader, which appends a module.exports at the end of the module, thus turning an old-school global script into a CommonJS module.
In this particular case, however, you don't need a loader at all because video.js is already aware of a CommonJS module system. Just write import videojs from "video.js";.
There is another minor problem, however. If you compile this with webpack, it will print a warning to the console:
WARNING in ../~/video.js/dist/video.js
Critical dependencies:
13:480-487 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ../~/video.js/dist/video.js 13:480-487
This is because webpack detects that this file has already been bundled somehow. Often it's better to include the actual src with all its tiny modules instead of one large dist because this way webpack is able to optimize the bundle in a better way. I've written down an exhaustive explanation about how to import legacy scripts with webpack.
Unfortunately, video.js does not include its src in the version deployed at npm, so you're forced to use the dist. In order to get rid of the error message and to improve webpack's build time, you can instruct webpack to skip video.js when parsing the code for require() statements by setting the module.noParse option in your webpack.config.js:
module: {
noParse: [
/node_modules[\\/]video\.js/
]
}
Usually it's safe to flag all pre-bundled modules (typically those with a dist folder) as noParse because they are already self-contained.
include SDN
<script src="//vjs.zencdn.net/5.11/video.min.js"></script>
webpack config:
config.externals = {
'video.js': 'videojs'
};

Categories