I am using a library that uses web workers for certain operations. To build my project, I am using babel, which polyfills and adds some global functions such as _asyncToGenerator. This works fine, aside from within the scope of said workers, where it is throwing me errors that _asyncToGenerator is undefined.
This is because babel polyfills in the global/window scope, but not the scope of each worker. How do I address this to make the polyfills also available in these scopes?
Related
This is my problem: I created a library to use within Chrome extensions. This library exports two classes, one of which should be imported in the background script and one in the content scripts.
The background script (and other scripts that are used in the extension pages) can handle modules, so I would like to use the native "import"/"export" feature of ES6 Modules.
The content scripts do not support modules. That means that if I use the "export" keyword in my library script, that will throw an error, and I won't be able to use the library anymore.
Currently, I'm not implementing modules at all, and that solves the problem, but I would like to implement this functionality, so that it can be used when someone has access to it.
Is there a way to offer my library functionality as both a module and a non-module for both kind of scripts? Is that actually something that I should do?
In the end, I set up two git branches:
1 - In the first one, I just kept the file without the "export", so no ES6 modules capabilities
2 - This other branch, I decided to set it up to be published on NPM, and in this one I exported my classes. If you use NPM for your development, it's already very probable that you also have a bundler like webpack to keep track of modules and dependencies.
Whenever I do a change, I do it in the master (no exports) branch, and then I merge the changes in the npm branch, to avoid writing the same code twice
I am unsure the differences between importing a JavaScript module in the following:
CommonJS
ES5
ES6
NodeJS
Typescript
Why are there so many ways to import javascript modules? Is "module" defined differently in different implementations? Are all doing the same thing but with different syntax?
There are no modules in ES5 and earlier. Various module systems (CommonJS, AMD, and the CommonJS-like ones in and Node.js and TypeScript) were created because there was no standard module system in JavaScript at the time, but it's a really useful thing to have. So the need got filled by tools and toolbuilders.
ES2015 (aka "ES6") created a standard syntax for modules in JavaScript which has now been adopted by all modern browsers, Node.js, and TypeScript. That standard syntax leaves the semantics of module identifiers up to the host environment, so leaders in the web community had to come to consensus for how to do them in browsers (and Node.js had to figure out how to do it in Node.js, etc.), so there was a bit of a delay between ES2015 coming out and your being able to use that syntax natively (though Webpack, Rollup, and such handled it).
There are some use cases where ES2015's static syntax doesn't quite do the job, so there's the import() (dynamic import) proposal which is already supported in some environments and will be in ES2020.
I have started working on an existing project based on Node.js. I was just trying to understand the flow of execution, where I encountered with some *.mjs files. I have searched the web where I found that these are module based JS-files.
I want to know how is it different from *.js files (how does it benefit)?
It indicates an ES6 module file.
Node.js's original module system is CommonJs (which uses require and module.exports).
Since Node.js was created, the ECMAScript module system (which uses import and export) has become standard and Node.js has added support for it.
Node.js will treat .cjs files as CommonJS modules and .mjs files as ECMAScript modules. It will treat .js files as whatever the default module system for the project is (which is CommonJS unless package.json says "type": "module",).
See also: Differences between ES6 module system and CommonJs
.MJS file
mjs an extension for EcmaScript modules
An MJS file is a source code file containing an ES Module (ECMAScript Module) for use with a Node.js application.
MJS files are written in JavaScript, and may also use the .JS extension outside of the Node.js context.
ES Modules allow web and application developers to organize code into smaller reusable components.
ECMAScript 6 (ES6) introduced the specification for ES Modules, providing a standard for implementing modules in JavaScript. As of 2018, all major web browsers support ES Modules.
However, the popularity of modularized JavaScript pre-dates ES6. Node.js, a JavaScript runtime environment, used CommonJS as the specification for modules. Because so many existing applications were built with CommonJS, when Node.js added support for native ES modules, it controversially introduced the MJS file extension to differentiate the two and prevent applications from breaking.
NOTE: Some developers informally refer to MJS files as "Michael Jackson Script" files.
For clarity. As for devs/humans, it's easy to distinguish between a module file(.mjs) and a normal javascript file(.js)... because it's not always easy to determine even if you examine the code in the file.
There are also performance benefits which gives you more reason to consider using it.
V8(JavaScript engine that powers Google Chrome) recommends the use of .mjs but it still depends on your situation. If you want to know more of it's advantages, check https://v8.dev/features/modules#mjs
Create-React-App uses Babel that converts my ES6 modules to CommonJS module and Webpack will bundle everything in single file that my browser can understand.
1) Why not use CommonJS modules directly and use Webpack as bundler?
2) Now that ES6 modules are supported in browsers, why don't we transpile React CommonJS modules to ES6 modules.
Go to your Chrome console and type in require, you will get the message require not defined.
Our browser, in particular Chrome, has no idea what CommonJS is, it has no idea what modules are.
But if you are looking to remove those restrictions in your project, you can make use of Electron.
If you run require inside of the Electron browser window you will get this:
f require(path) {
try {
exports.requireDepth += 1;
return mod.require(path);
} finally {
exports.requireDepth -= 1;
}
}
Chrome the browser has no idea what the above is, but the Electron browser window does. It has some additional capabilities that Chrome does not.
The Electron browser has a MainWindow object which has access to all the available modules the belong to the Nodejs runtime and access to all modules inside the browser as well. So access to CommonJS as well as fs, crypto, etcetera.
You can do `require('fs') and access the filesystem directly from the Electron browser console.
In short, I am saying that with Electron you can directly require in modules like you want without having to use Webpack.
CommonJS code will not allow you to write code using imports, arrow functions, destructuring, generators, class etc... This makes your developer's life easy and I do see below advantages:
Less code more for same functionality.
Less time required for writing same functionality.
As of chrome 61 + can process your ES6 code but other browser will not be supporting it. So you need to transpile ES6 code to common js code so that it is consistent across browsers.
I know that if there are multiple JS files to be rendered by the browser, which apparently have identifiers inside, the global scope is polluted by this identifiers. I also know that one way to avoid this is using modules which(in my understanding) are just objects which have the aformentioned identifiers as members, thus sort of imitating C++ namespaces. I am also learning Node.js and there is a built in module system which eases this task so my question is: how to use modules in js files that are sent to the browser to be rendered?
Thanks.
Tools like browserify and WebPack are exactly what you are looking for (I personally prefer browserify over WebPack). Have a look at this answer, it explains a lot of your concerns.
In Node.JS, you can export a module using module.exports keyword, but you cannot just import those modules in your browser by just requiring them in a <script> tag. That's because, the browser doesn't understand the module system and everything works in the context of a global window object there, so module.exports simply becomes window.module.exports which I'm sure you'll not want. Hence you use tools like browserify that process the Node.JS scripts into something that your browser will understand.
This problem is usually solved by module bundlers or module loaders (e.g Webpack, Browserify, RequireJS). They are able to understand relations between your JS modules, skip unused modules and produce output that just works in your browser. All of that without the need to worry too much about global scope if you follow some conventions.
Some time ago, before ES6, two different approaches to this problem were widely used:
CommonJS:
var module = require('my-module');
widely known from Node.js
AMD:
define(['jquery'] , function ($) {
return function () {};
});
Which was suited for browser usage since it by design supported asynchronous loading of modules.
Then ES6 was introduced with native support for modules:
import * as lib from 'lib';
Main problem with new technology in web is that you often have variety of browsers to support which for a long time prevented developers from using new features. Nowadays, we have code transpilers and sophisticated code bundlers (e.g. Webpack). With their help you can use latest version of language, compile and bundle your code and at the end single "bundle.js" file is emitted which supports older browsers at the cost of slower execution times.