How to use ES6-symbol polyfill - javascript

I have an Symbol is not defined in IE so I tried to use this library as polyfill
https://github.com/medikoo/es6-symbol
As inexperienced as I am, I do not really know how to include it so that it use as global.
In detail, in my code I include it using requirejs as:
requirejs.config({
paths:
{ 'symbol': 'libs/es6-symbol/index' }
})
//define it in app entry point
require([
'symbol'],
function (sy) {
//What should I do?
}
How should i approach this?

You cannot just load the index.js of es6-symbol with RequireJS. If you just look at it, you'll see:
'use strict';
module.exports = require('./is-implemented')() ? Symbol : require('./polyfill');
This is valid CommonJS code but not valid AMD code. RequireJS supports AMD natively, not CommonJS. To use CommonJS code with RequireJS you'd have at a minimum to wrap the code above in a define call, which means having a build step.
Ultimately, you should heed the advice of the README:
To port it to Browser or any other (non CJS) environment, use your favorite CJS bundler. No favorite yet? Try: Browserify, Webmake or Webpack
Research the bundlers, pick one, write a build configuration for it, and if you still have trouble you can ask on this site.

Related

how code splitting works with import/export and babel and webpack?

I am trying to answer,
when to use import/export and when to use require()/module.exports? But as I try to dig, it seems to get complicated.
Here's my understanding
require()/module.exports: this is nodejs implementation of the module system. This loads the modules syncronously.
with es6, we can use import/export. the docs says
The import statement is used to import bindings which are exported by another module. Imported modules are in strict mode whether you declare them as such or not. The import statement cannot be used in embedded scripts unless such script has a type="module".
Ques1: How does this work with babel or webpack or browsers in general?
As I was exploring I came across stuff like CommonJs, requireJs, Asynchronous Module Definition (AMD)
Ques2: I am more interested in knowing the timeline as how these things evolved in javascript ?
How does this work with babel or webpack or browsers in general?
Babel and Webpack follow the ES spec and transpile the import / export statement to one single file. As they also support the require syntax, they usually transpile the import statements to require() calls and the export statements to module exports, and then ship with a custom loader for modules., If you got for example:
// A.js
export default function() { }
// B.js
import A from "./A";
A();
Then it gets transpiled to the following require syntax:
//A.js
exports.default = function() {};
//B.js
var A = require("./A").default;
A();
That could then get wrapped to something like:
(function() { // prevent leaking to global scope
// emulated loader:
var modules = {};
function require(name) { return modules[name]; }
function define(name, fn) {
var module = modules[name] = { exports: {} };
fn(module, module.exports, require);
}
// The code:
define("A", function(module, exports, require) {
// A.js
exports.default = function() { };
});
define("B", function(module, exports, require) {
// B.js
var A = require("A").default;
A();
});
})();
how these things evolved in javascript ?
A few years ago, writing JS was restricted to browsers, and the only way to load multiple js sources was to use multiple <script> tags and use the global object to exchange functionality. That was ugly.
Then Nodejs was invented and they needed a better way to work with modules and invented the require() thing.
The writers of the spec saw a need for a native syntax for that, so import / export were introduced.
Babel and others then wrote transpilers.
What webpack the bundler does is the following:
You specify an input file in the config
You specify an output file the config
Webpack will look at all the files which the input file requires (commomJS module system) or imports (ES6 module system). It then funnels the code based on file name extention through loaders. Loaders can transpile the individual files to code the browser can understand. An example of a loader is babel or the sass/scss compiler.
After the different files are transpiled with loaders, the plugins can work at the
transform the bundle of generated code into something else. The bundle is just a bunch of code which together forms piece of functionality
In won't go into detail in the internals of webpack too deeply, but the most important thing to understand is:
You use webpack so you can use split up your code in multiple files, which makes them more maintainable and easier to work with. However then requesting all these files by the client would be horrible for performance (many HTTP requests overhead). Therefore, we bundle the files into one file, or a couple so this overhead is reduced.
Generally, you should write all modern code with import/export syntax if you are using a bundler like webpack, or translating with Babel... npm modules may favor require/module syntax but you can still import them.
Also worth noting is the import() method which returns a promise that should resolve to the root module being imported asynchronously. Webpack may bundle these as asynchronous modules if you have it configured to do so.
In practice the resolution through tooling like babel and webpack will fallback to node-style behaviors against the node_modules lookup, where the standard is transport paths, favoring relative paths. Additional support is per environment.
You can experiment with esm support in modern browsers and in current node (behind a flag as of this answer). The behaviors are somewhat inconsistent, but well defined. When in doubt, experiment and try.

Migrating from requirejs to webpack

I'm migrating/moving a project based on require.js to webpack v3. Since all my modules are using the following syntax:
define([modules,..], function(mod1,..)
Which declares which modules to use, and assigns the modules to the variables in the anonymous function. This seems to be deprecated since v2 of webpack. I can't find any information about this (except for the documentation for web pack v1).
Should I rewrite all my modules to the commonjs (including dependencies) or are there any smart way to use the AMD modules?
Help much appreciated :-)
Regards
AMD never found much use outside of requirejs so likely you will need to convert. There are tools that will help:
https://github.com/anodynos/uRequire can convert code from AMD -> UMD / CommonJS
There are caveats from (https://github.com/anodynos/uRequire/wiki/nodejs-Template):
Runtime translation of paths like models/PersonModel to ../../models/PersonModel, depending on where it was called from. You 'll still get build-time translated bundleRelative paths, to their nodejs fileRelative equivalent.
For most projects this is not an issue.
Can't use the asynchronous version of require(['dep'], function(dep){...})
You should be able to use the synchronous version of require. If using webpack2 you can use System.import or require.ensure
Can't run requirejs loader plugins, like text!... or json!...
You will find webpack version of all of these plugins
There's no mapping of /, ie webRootMap etc or using the requirejs.config's {baseUrl:"...."} or {paths:"lib":"../../lib"}
This can be replicated with https://www.npmjs.com/package/babel-plugin-module-alias
The CaptEmulation's answer is not valid for newer Webpack versions. Webpack supports AMD natively (neither additional loaders, nor plugins need to be installed). A thorough instruction is available here: https://webpack.js.org/api/module-methods.
This fact may easily go unnoticed when one tries to rewrite a RequireJS-based build to Webpack, as RequireJS uses relative paths without the trailing ./, e.g.
define('app/dep1', function(dep1) { ... });
which will not pass in Webpack without additional configuration (assuming that both require.config.js and webpack.config.js are in the same directory):
{
resolve: {
modules: [ './', ... ] // other entries possible here
}
}

When adding AMD support to a library, should it also list its dependencies in define()

I am looking to add AMD support to a library although don't fully understand it. I have the following code that adds AMD support:
if (typeof define === "function" && define.amd) {
define(["imagesloaded", "hammer"], defineSequence);
} else {
sequence = defineSequence(imagesLoaded, Hammer);
}
The library depends on third-party libraries imagesLoaded and Hammer. I have listed them as dependencies in define() but I am concerned as to whether this limits a developer who uses my plugin to a specific file structure and naming convention whereby imagesloaded, hammer, and sequence all have to exist at the same directory level.
Is the above code correctly enabling AMD support and is this restriction to be expected?
Update: An example of my paths config as explained in the correct answer:
require.config({
baseUrl: 'scripts',
paths: {
imagesLoaded: 'imagesloaded.pkgd.min',
Hammer: 'hammer.min'
}
});
Path config can be used for defining the path to the dependencies. So you dont have to worry about users directory structure.
You should only provide information of what AMD module you are expecting as dependency and what functionality it should provide. It may even be abstract like $ (coming from jquery, zepto or sizzle)

Is XRegExp compatible with RequireJS?

I downloaded RequireJS single page app sample. In the www/lib folder, I put the XRegExp source xregexp-all.js (version 2.0.0).
In www/app/main.js, I added:
var xregexp = require('xregexp-all');
print(typeof(xregexp));
The console output is:
undefined
However, requireJS doesn't emit any error messages. Am I doing something wrong?
Yes, you are doing something wrong. Only some versions of the files distributed for XRegExp perform the required define call that defines them as RequireJS modules. The one you are using does not contain that call. You can determine this for yourself by searching for the define( string in the file.
You'll need to add a shim to your configuration so that RequireJS can load XRegExp or you'll have to use a version of the file that calls define, like for instance this one which is XRegExp 3.0.0 (still alpha). If you want to use 2.x then your config would be something like:
paths: {
xregexp: "../whatever/your/path/actualy/is/xregexp-all"
}
shim: {
xregexp: {
exports: "XRegExp",
},
}
Note that this config normalizes the module name to xregexp, so you would have to require it as xregexp, not xregexp-all. In general, I prefer not to have things like -all or .min in my module names since these may change depending on the situation.
The shim tells RequireJS that the value it should export when xregexp is required is that of the global symbol XRegExp. This is generally how you handle modules that are not AMD-aware.
A quick search for "amd", or "define" in a library's source code should be the quickest way to tell if it supports AMD scheme. If not, then it's not (doh!)
However, if the library exposes globals, then you can use RequireJS shim to load it up as well as path to tell RequireJS where to retrieve it.
// Exporting a traditional library through RequireJS
require.config({
paths : {
jaykweri : 'path/to/jQuery' // moduleName : pathToModule
},
shim : {
jaykweri : {exports : '$'} // exporting the global
}
});
// Using that library in requireJS
define(['jaykweri'],function(globl){
// globl === $
});

Node.js require() vs RequireJS?

Hello with RequireJS I can set a base path like this: base : './app/' so when I am in ./app/foo/bar/ for example and I have a script where I use require('foo'); RequireJS then would search for ./app/foo.js and not in node_module folder or in ./app/foo/bar/foo.js this comes handy when you have a kind of structure where it would be much cleaner for you as a developer to see the dependencies instead of having ../../foo.js. I could have ./app/foo.js and ./app/foo/foo.js and ./app/foo/bar/foo.js it would be much more cleaner to have:
require('foo');
require('foo/foo');
require('foo/bar/foo');
rather than:
require('../../foo');
require('../foo');
require('./foo');
Now you could say why not change the name and not have foo everywhere, let's say that we can't for any reason…
Another lack of feature that I see in node's require method against RequireJS is the ability of setting path mapping, if I have a directory named ./app/super-sized-directory-name/ in RequireJS I could simply do 'big-dir' : 'super-sized-directory-name' and then I could simply use require('./app/big-dir/foo') with Node.js's require method this is not possible as far as I know…
--alias, -a Register an alias with a colon separator: "to:from"
Example: --alias 'jquery:jquery-browserify'
You can register aliases with browserify, so that covers your renaming.
As for your rooted absolute paths, that can't really be done. As mentioned modul8 has a namespacing mechanism to solve this.
I would recommend you pong SubStack in #stackvm on freenode and ask him directly.
It may or may not help you, but I believe the Dojo Frameworks AMD Loader is API compatible with RequireJS and providing you are using a new microkernel does not pollute the global namespace.
I believe it only has require() and define() in the global namespace now.
Anyway their method of dealing with this is to do something like:
require(["dojo/node!util"], function(util){
// Module available as util
});
The documentation is at http://dojotoolkit.org/reference-guide/1.8/dojo/node.html
Use uRequire which provides a 'bridge' between nodejs require and AMD define modules, without reinventing the wheel (it is build on top of the two standards). It basically converts modules from AMD or commonJS format to the other format or UMD that runs smoothly on both nodejs & the browser.
It is also translating dependency paths with flexible path conventions, so you can have either '../../foo' or 'bar/foo' depending on which makes more sense at the point you are at.
Your AMD or UMD modules are loaded asynchronously on browser (using AMD/requireJs or other AMD loader) and on node the asynchronous require(['dep1', 'dep2'], function(dep1,dep2){...}) is also simulated.

Categories