I try to use ecmascript 6 modules system for first time. I use traceur compiler. Given two es6 files:
// app.js
export function row() {
alert('row');
}
// init.js
import { row } from 'public_js/app';
row();
Traceur (I use grunt-traceur task) compiles them to:
// app.js
System.register("public_js/app", [], function() {
"use strict";
var __moduleName = "public_js/app";
function row() {
alert('row');
}
return {get row() {
return row;
}};
});
// init.js
System.register("public_js/init", [], function() {
"use strict";
var __moduleName = "public_js/init";
var row = System.get("public_js/app").row;
row();
return {};
});
I include compiled version of init.js to my HTML via simple script tag:
<script src="/path/to/compiled/init.js" type="module"></script>
And nothing happens. I don't see my alert. What am I doing wrong?
By pre-compiling your code as modules to ES5, you are now taking it out of the world of the automatic import/module loading system in ES6 and you need to use ES5 mechanisms to load it. So, you need to include the compiled code without the type=module attribute and then get() the module that kicks off the rest of the world.
So, the following works for me:
<script src="/path/to/compiled/app.js"></script>
<script src="/path/to/compiled/init.js"></script>
<script>
System.get('public_js/init');
</script>
Since you are pre-compiling the code, I recommend that you concatenate all of the compiled code into a single JS file to avoid including them all.
If you use Traceur without compiling your code first, then you can live within the ES6 constructs. This includes type="module" and/or import 'module-name'.
Edit
Thinking about this further, app.js is correctly compiled as a module. init.js, however, doesn't need to be compiled as a module. You are compiling the code with the --module flag. If, instead, you compile init.js with the --script flag, it will not encapsulate the init code as a module, and you don't need to call System.get by hand. Just something to think about.
Related
I am writing an application with the Node.js, Express.js, and Jade combination.
I have file client.js, which is loaded on the client. In that file I have code that calls functions from other JavaScript files. My attempt was to use
var m = require('./messages');
in order to load the contents of messages.js (just like I do on the server side) and later on call functions from that file. However, require is not defined on the client side, and it throws an error of the form Uncaught ReferenceError: require is not defined.
These other JavaScript files are also loaded at runtime at the client, because I place the links at the header of the webpage. So the client knows all the functions that are exported from these other files.
How do I call these functions from these other JavaScript files (such as messages.js) in the main client.js file that opens the socket to the server?
This is because require() does not exist in the browser/client-side JavaScript.
Now you're going to have to make some choices about your client-side JavaScript script management.
You have three options:
Use the <script> tag.
Use a CommonJS implementation. It has synchronous dependencies like Node.js
Use an asynchronous module definition (AMD) implementation.
CommonJS client side-implementations include (most of them require a build step before you deploy):
Browserify - You can use most Node.js modules in the browser. This is my personal favorite.
Webpack - Does everything (bundles JavaScript code, CSS, etc.). It was made popular by the surge of React, but it is notorious for its difficult learning curve.
Rollup - a new contender. It leverages ES6 modules and includes tree-shaking abilities (removes unused code).
You can read more about my comparison of Browserify vs (deprecated) Component.
AMD implementations include:
RequireJS - Very popular amongst client-side JavaScript developers. It is not my taste because of its asynchronous nature.
Note, in your search for choosing which one to go with, you'll read about Bower. Bower is only for package dependencies and is unopinionated on module definitions like CommonJS and AMD.
I am coming from an Electron environment, where I need IPC communication between a renderer process and the main process. The renderer process sits in an HTML file between script tags and generates the same error.
The line
const {ipcRenderer} = require('electron')
throws the Uncaught ReferenceError: require is not defined
I was able to work around that by specifying Node.js integration as true when the browser window (where this HTML file is embedded) was originally created in the main process.
function createAddItemWindow() {
// Create a new window
addItemWindown = new BrowserWindow({
width: 300,
height: 200,
title: 'Add Item',
// The lines below solved the issue
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})}
That solved the issue for me. The solution was proposed here.
ES6: In HTML, include the main JavaScript file using attribute type="module" (browser support):
<script type="module" src="script.js"></script>
And in the script.js file, include another file like this:
import { hello } from './module.js';
...
// alert(hello());
Inside the included file (module.js), you must export the function/class that you will import:
export function hello() {
return "Hello World";
}
A working example is here. More information is here.
Replace all require statements with import statements. Example:
// Before:
const Web3 = require('web3');
// After:
import Web3 from 'web3';
It worked for me.
In my case I used another solution.
As the project doesn't require CommonJS and it must have ES3 compatibility (modules not supported) all you need is just remove all export and import statements from your code, because your tsconfig doesn't contain
"module": "commonjs"
But use import and export statements in your referenced files
import { Utils } from "./utils"
export interface Actions {}
Final generated code will always have(at least for TypeScript 3.0) such lines
"use strict";
exports.__esModule = true;
var utils_1 = require("./utils");
....
utils_1.Utils.doSomething();
This worked for me
Get the latest release from the RequireJS download page
It is the file for RequestJS which is what we will use.
Load it into your HTML content like this:
<script data-main="your-script.js" src="require.js"></script>
Notes!
Use require(['moudle-name']) in your-script.js,
not require('moudle-name')
Use const {ipcRenderer} = require(['electron']),
not const {ipcRenderer} = require('electron')
Even using this won't work. I think the best solution is Browserify:
module.exports = {
func1: function () {
console.log("I am function 1");
},
func2: function () {
console.log("I am function 2");
}
};
-getFunc1.js-
var common = require('./common');
common.func1();
window = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
I confirm. We must add:
webPreferences: {
nodeIntegration: true
}
For example:
mainWindow = new BrowserWindow({webPreferences: {
nodeIntegration: true
}});
For me, the problem has been resolved with that.
People are asking what is the script tag method. Here it is:
<script src='./local.js'></script>.
Or from network:
<script src='https://mycdn.com/myscript.js'></script>
You need plugin the right url for your script.
I was trying to build metronic using webpack. In my package.json I had to remove the "type": "module" section.
I'm developing a plugin for a tool. The plugin is just a zip file, and the tool only looks for and loads main.html file. Thefore, any JS must be inlined in the HTML file.
I'm trying to develop with separate Typescript files and then have webpack bundle all the .ts files into a bundle.js and inline it in the HTML.
I managed to this but there's one problem. How to call the logic in the bundle from the HTML?
Webpack creates __webpack_modules__ IIFE variables for the code in the bundle.
<head>
<script>bundled JS</script>
</head>
<body>
</body>
<script>
// How to call here an init() function in the bundle?
</script>
I tried to setup iife: false with no luck:
You'll need to explicitly export to the global object by assigning to window.
<script>
(() => {
function myFn() { console.log('myFn ran') }
window.myFn = myFn // assign to global object here.
})()
</script>
<script>
myFn()
</script>
Then if you want typescript type available for that, see: Create a global variable in TypeScript
It looks like you want to export your bundle as a library that we can use in a different script. If so, the option output#library comes to help so the only thing you need to do is to export it as library with umd format which works great for both node and browser envs.
{
output: {
// ...
library: {
name: 'yourLib', // you then can access it via window: `window.youLib`
type: 'umd',
umdNamedDefine: true,
},
}
I have an extremely simple single-page dashboard that does things like grab the weather, the subway alerts, etc. and I refresh it locally on my machine. It looked like:
project/
index.html
jquery-3.3.1.min.js
script.js
And I wanted to convert it to TypeScript. I ported script.js to TypeScript, but in order to use jQuery had to download the definition file from here. I now have:
project/
index.html
jquery.d.ts
script.ts
The first two lines of my TypeScript file are:
/// <reference path ="./jquery.d.ts"/>
import * as $ from "jquery"
When I run tsc *.ts, it compiles my script successfully, but the first four lines of the resulting/compiled JavaScript file are:
"use strict";
exports.__esModule = true;
/// <reference path ="./jquery.d.ts"/>
var $ = require("jquery");
And this fails in my browser with:
exports.__esModule = true; // Can't find variable: exports
I'm a pretty weak front-end developer beyond HTML/JS/jQuery, so I'm not sure where to start - I did some Googling but not much came up.
If you mean so...
use declare var $: JQuery if the type is defined
else use declare vas $: any
for the case that your editor (f.e. VSCode) supports script var declarations use
{
name: "$",
type: JQuery (or any),
ofReference: {
scriptSrc: ["*jquery.js", "*jquery.min.js", "*code.jquery*"]
}
}
Is it possible to "require" an entire folder using requireJS.
For example, I have a behaviors folder with a ton of behavior js files. I'd really like to be able to simply use require(['behaviors/*'], function() {...}); to load everything in that folder rather than having to keep that list up to date. Once compressed and optimized I'd have all those files lump together, but for development it's easier to work with them individually.
javascript in browser has no filesystem access and so it can't scan a directory for files. If you are building your app in a scripting language like php or ruby you could write a script that scans the directory and adds the file names to the require() call.
I don't know if I can recommend this approach anymore. I think the more explicit way to do this is by manually "requiring"/"exporting" the functionality you need. The exception I think is if you have a "namespace" of files that you want exported see below "Babel and ES6 Module Import Declarations (export-namespace-from) or see below "Babel and ES6 Module Import Declarations.
These solutions also assume that you have a meaningful file structure - where file names become part of that "require" * definition.
However, if you still need to do this there are a few existing tools and methods that might provide the behavior that you're looking for.
Possible Solutions
Babel and ES6 Module Import Declarations (plugin-export-namespace-from)
Have a setup that is ES6 compliant.
You need to update your .babelrc file to include babel-plugin-proposal-export-namespace-from.
Use export namespace plugin by writing syntax like the following:
common/index.js
export * from './common/a'; // export const a = false;
export * from './common/b'; // export const b = true;
main.js
import { a, b } from './common';
console.log(a); // false
console.log(b); // true
Babel and ES6 Module Import Declarations (plugin-wildcard)
Have a setup that is ES6 compliant.
You need to update your .babelrc file to include babel-plugin-wildcard.
Use wildcard namespace plugin by writing syntax like the following:
main.js
import { a, b } from './common/*'; // imports './common/a.js' and './common/b.js'
console.log(a); // false
console.log(b); // true
RequireJS (Now Outdated)
Download and install require-wild npm install require-wild
Configure the declaration as follows
grunt.initConfig({
requireWild: {
app: {
// Input files to look for wildcards (require|define)
src: ["./**/*.js"],
// Output file contains generated namespace modules
dest: "./namespaces.js",
// Load your require config file used to find baseUrl - optional
options: { requireConfigFile: "./main.js" }
}
}
});
grunt.loadNpmTasks("require-wild");
grunt.registerTask('default', ['requireWild']);
Then run the grunt task. Your file will be generated. Modify your setup to load namespaces.js
require(['namespaces'], function () { ... });
This now allows modules under src to use dependencies glob pattern matching.
require(['behaviors/**/*'], function (behaviors) { }
I know this is old, but I'd like to share my solution:
For this solution you need JQuery
1) Create a bash script that will list all the js files in
"MyDirectory/", and save it to "directoryContents.txt":
#!/bin/bash
#Find all the files in that directory...
for file in $( find MyDirectory/ -type f -name "*.js" )
do
fileClean=${file%.js} #Must remove .js from the end!
echo -n "$fileClean " >> MyDirectory/directoryContents.txt
done
File will look like this:
MyDirectory/FirstJavascriptFile MyDirectory/SecondJavascriptFile
MyDirectory/ThirdJavascriptFile
Problem with my script! Puts an extra " " at the end, that messes things up! Make sure to remove the excess space at the end of directoryContents.txt
2) Then in your Client side JS code:
do a "GET" request to retrieve the text file
For each entry (split by the space), 'require' that file:
.
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
//Done loading this one file
});
}
}, "text");
I was having a problem with this code not finishing before my other code, so Here's my extended answer:
define([''], function() {
return {
createTestMenu: function()
{
this.loadAllJSFiles(function(){
//Here ALL those files you need are loaded!
});
},
loadAllJSFiles: function(callback)
{
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
var currentFileNum = 0;
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
currentFileNum++;
//If it's the last file that needs to be loaded, run the callback.
if (currentFileNum==allJsFilesInFolder.length)
{
console.log("Done loading all configuration files.");
if (typeof callback != "undefined"){callback();}
}
});
}
}, "text");
}
}
});
What I ended up doing was everytime my Node server boots, it will run the bash script, populating directoryContents.txt. Then My client side just reads directoryContents.txt for the list of files, and requires each in that list.
Hope this helps!
There isn't really a way to do this conceptually on the fly (that I know of).
There's a few work arounds though:
Use grunt and concat and then just require that behemoth...I know, kinda sucky.
What I think is a better solution... use a require hierarchy like so:
require('/js/controllers/init', function(ctrls){
ctrls(app, globals);
});
// /js/controllers/init.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
var indexModule = index(app, globals);
var indexModule = posts(app, globals);
return app || someModule;
};
});
// /js/controllers/index.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
function method1(){}
function method2(){}
return {
m1: method1,
m2: method2
};
};
});
Note that "protagonist" function. That allows you to initialize modules before their use, so now you can pass in a 'sandbox' -- in this case app and globals.
Realistically, you wouldn't have /js/controllers/index.js... It should probably be something like /js/controllers/index/main.js or /js/controllers/index/init.js so that there is a directory adjacent to (sibling of) /js/controllers/init.js called "index". This will make your modules scalable to a given interface -- you can simply swap modules out and keep your interface the same.
Hope this helps! Happy coding!
I wrote a library to solve this problem. Eventually someone else came along and improved my library, here it is:
https://github.com/smartprocure/directory-metagen
You can use my lib with Gulp or whatever - it generates metadata for your project and RequireJS can use that metadata to require the desired files from the filesystem.
Using this lib will produce a RequireJS module that looks something like this:
define(
[
"text!app/templates/dashboardTemplate.ejs",
"text!app/templates/fluxCartTemplate.ejs",
"text!app/templates/footerTemplate.ejs",
"text!app/templates/getAllTemplate.ejs",
"text!app/templates/headerTemplate.ejs",
"text!app/templates/homeTemplate.ejs",
"text!app/templates/indexTemplate.ejs",
"text!app/templates/jobsTemplate.ejs",
"text!app/templates/loginTemplate.ejs",
"text!app/templates/overviewTemplate.ejs",
"text!app/templates/pictureTemplate.ejs",
"text!app/templates/portalTemplate.ejs",
"text!app/templates/registeredUsersTemplate.ejs",
"text!app/templates/userProfileTemplate.ejs"
],
function(){
return {
"templates/dashboardTemplate.ejs": arguments[0],
"templates/fluxCartTemplate.ejs": arguments[1],
"templates/footerTemplate.ejs": arguments[2],
"templates/getAllTemplate.ejs": arguments[3],
"templates/headerTemplate.ejs": arguments[4],
"templates/homeTemplate.ejs": arguments[5],
"templates/indexTemplate.ejs": arguments[6],
"templates/jobsTemplate.ejs": arguments[7],
"templates/loginTemplate.ejs": arguments[8],
"templates/overviewTemplate.ejs": arguments[9],
"templates/pictureTemplate.ejs": arguments[10],
"templates/portalTemplate.ejs": arguments[11],
"templates/registeredUsersTemplate.ejs": arguments[12],
"templates/userProfileTemplate.ejs": arguments[13]
}
});
You can then require modules in your front-end like so:
var footerView = require("app/js/jsx/standardViews/footerView");
however, as you can see this is too verbose, so the magic way is like so:
name the dependency above as allViews!
now you can do:
var allViews = require('allViews');
var footerView = allViews['standardViews/footerView'];
There are two advantages to requiring directories whole:
(1) in production, with the r.js optimizer, you can point to one dependency (module A) and it can then easily trace all of A's dependencies that represent a entire directory
(2) in development, you can require whole directories up front and then use synchronous syntax to require dependencies because you know they have already been loaded
enjoy "RequireJS-Metagen"
https://github.com/smartprocure/directory-metagen
https://www.npmjs.com/package/requirejs-metagen
https://github.com/ORESoftware/requirejs-metagen
Is it possible to use require() (or something similar) on client side?
Example
var myClass = require('./js/myclass.js');
You should look into require.js or head.js for this.
I've been using browserify for that. It also lets me integrate Node.js modules into my client-side code.
I blogged about it here: Add node.js/CommonJS style require() to client-side JavaScript with browserify
If you want to have Node.js style require you can use something like this:
var require = (function () {
var cache = {};
function loadScript(url) {
var xhr = new XMLHttpRequest(),
fnBody;
xhr.open('get', url, false);
xhr.send();
if (xhr.status === 200 && xhr.getResponseHeader('Content-Type') === 'application/x-javascript') {
fnBody = 'var exports = {};\n' + xhr.responseText + '\nreturn exports;';
cache[url] = (new Function(fnBody)).call({});
}
}
function resolve(module) {
//TODO resolve urls
return module;
}
function require(module) {
var url = resolve(module);
if (!Object.prototype.hasOwnProperty.call(cache, url)) {
loadScript(url);
}
return cache[url];
}
require.cache = cache;
require.resolve = resolve;
return require;
}());
Beware: this code works but is incomplete (especially url resolving) and does not implement all Node.js features (I just put this together last night).
YOU SHOULD NOT USE THIS CODE in real apps but it gives you a starting point. I tested it with this simple module and it works:
function hello() {
console.log('Hello world!');
}
exports.hello = hello;
I asked myself the very same questions. When I looked into it I found the choices overwhelming.
Fortunately I found this excellent spreadsheet that helps you choice the best loader based on your requirements:
https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ
Take a look at requirejs project.
I have found that in general it is recommended to preprocess scripts at compile time and bundle them in one (or very few) packages with the require being rewritten to some "lightweight shim" also at compile time.
I've Googled out following "new" tools that should be able to do it
http://mixu.net/gluejs/
https://github.com/jrburke/almond
https://github.com/component/builder2.js
And the already mentioned browserify should also fit quite well - http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/
What are the module systems all about?
Older Stack Overflow explanation - Relation between CommonJS, AMD and RequireJS?
Detailed discussion of various module frameworks and the require() they need is in Addy Osmani - Writing Modular JavaScript With AMD, CommonJS & ES Harmony
You can create elements to the DOM, which loads items.
Like such:
var myScript = document.createElement('script'); // Create new script element
myScript.type = 'text/javascript'; // Set appropriate type
myScript.src = './js/myclass.js'; // Load javascript file
Simply use Browserify, what is something like a compiler that process your files before it go into production and packs the file in bundles.
Think you have a main.js file that require the files of your project, when you run browserify in it, it simply process all and creates a bundle with all your files, allowing the use of the require calls synchronously in the browser without HTTP requests and with very little overhead for the performance and for the size of the bundle, for example.
See the link for more info: http://browserify.org/
Some answers already - but I would like to point you to YUI3 and its on-demand module loading. It works on both server (node.js) and client, too - I have a demo website using the exact same JS code running on either client or server to build the pages, but that's another topic.
YUI3: http://developer.yahoo.com/yui/3/
Videos: http://developer.yahoo.com/yui/theater/
Example:
(precondition: the basic YUI3 functions in 7k yui.js have been loaded)
YUI({
//configuration for the loader
}).use('node','io','own-app-module1', function (Y) {
//sandboxed application code
//...
//If you already have a "Y" instance you can use that instead
//of creating a new (sandbox) Y:
// Y.use('moduleX','moduleY', function (Y) {
// });
//difference to YUI().use(): uses the existing "Y"-sandbox
}
This code loads the YUI3 modules "node" and "io", and the module "own-app-module1", and then the callback function is run. A new sandbox "Y" with all the YUI3 and own-app-module1 functions is created. Nothing appears in the global namespace. The loading of the modules (.js files) is handled by the YUI3 loader. It also uses (optional, not show here) configuration to select a -debug or -min(ified) version of the modules to load.
Here's a solution that takes a very different approach: package up all the modules into a JSON object and require modules by reading and executing the file content without additional requests.
https://github.com/STRd6/require/blob/master/main.coffee.md
STRd6/require depends on having a JSON package available at runtime. The require function is generated for that package. The package contains all the files your app could require. No further http requests are made because the package bundles all dependencies. This is as close as one can get to the Node.js style require on the client.
The structure of the package is as follows:
entryPoint: "main"
distribution:
main:
content: "alert(\"It worked!\")"
...
dependencies:
<name>: <a package>
Unlike Node a package doesn't know it's external name. It is up to the pacakge including the dependency to name it. This provides complete encapsulation.
Given all that setup here's a function that loads a file from within a package:
loadModule = (pkg, path) ->
unless (file = pkg.distribution[path])
throw "Could not find file at #{path} in #{pkg.name}"
program = file.content
dirname = path.split(fileSeparator)[0...-1].join(fileSeparator)
module =
path: dirname
exports: {}
context =
require: generateRequireFn(pkg, module)
global: global
module: module
exports: module.exports
PACKAGE: pkg
__filename: path
__dirname: dirname
args = Object.keys(context)
values = args.map (name) -> context[name]
Function(args..., program).apply(module, values)
return module
This external context provides some variable that modules have access to.
A require function is exposed to modules so they may require other modules.
Additional properties such as a reference to the global object and some metadata
are also exposed.
Finally we execute the program within the module and given context.
This answer will be most helpful to those who wish to have a synchronous node.js style require statement in the browser and are not interested in remote script loading solutions.
I find the component project giving a much more streamlined workflow than other solutions (including require.js), so I'd advise checking out https://github.com/component/component . I know this is a bit late answer but may be useful to someone.
Here's a light weight way to use require and exports in your web client. It's a simple wrapper that creates a "namespace" global variable, and you wrap your CommonJS compatible code in a "define" function like this:
namespace.lookup('org.mydomain.mymodule').define(function (exports, require) {
var extern = require('org.other.module');
exports.foo = function foo() { ... };
});
More docs here:
https://github.com/mckoss/namespace
The clientside-require library provides an asynchronous load() function that can be used to load any JS file or NPM module (which uses module.exports), any .css file, any .json, any .html, any any other file as text.
e.g.,
npm install clientside-require --save
<script src = '/node_modules/clientside-require/dist/bundle.js'></script>
<script>
load('color-name') // an npm module
.then(color_name=>{
console.log(color_name.blue); // outputs [0, 0, 255]
})
</script>
A really cool part of this project is that inside of any load()ed script, you can use the synchronous require() function the same way you would expect in node.js!
e.g.,
load('/path/to/functionality.js')
and inside /path/to/functionality.js:
var query_string = require("qs") // an npm module
module.exports = function(name){
return qs.stringify({
name:name,
time:new Date()
}
}
That last part, implementing the synchronous require() method, is what enables it to utilize NPM packages built to run on the server.
This module was designed to implement the require functionality as closely as possible in the browser. Disclaimer: I have written this module.
Yes it is very easy to use, but you need to load javascript file in browser by script tag
<script src="module.js"></script>
and then user in js file like
var moduel = require('./module');
I am making a app using electron and it works as expected.