My javascript app is for a kiosk and is only targeting the Chrome browser. I'm using Chrome version 65. I am trying to use ES6 modules without using a transpiler like Babel. My code was originally:
in index.html:
<script src="js/index.js"></script>
index.js:
import Main from './classes/Main.js';
const init = () => {
const app = new Main();
};
init();
Main.js:
export default class Main {
constructor() {
}
}
Originally I got the error "Uncaught SyntaxError: Unexpected identifier" from index.js line 1. Then based on ES6 module Import giving "Uncaught SyntaxError: Unexpected identifier" I added 'type="module"' to the html tag:
<script type="module" src="js/index.js"></script>
This did load, but it takes my browser about 15 seconds to load index.js and main.js according to the network profiler. What could be going on?
So I ran some tests on my local box. I have a simple NodeJs server running with the following three files:
index.html
<!doctype html>
<html>
<head>
<title>es6 Module test</title>
<script>
console.time('load module');
console.time('time until constructor called');
</script>
<script type="module" src="module.js"></script>
<script>
console.timeEnd('load module');
</script>
</head>
<body>
See console output.
</body>
</html>
module.js
import Main from './Main.js';
const init = () => {
const app = new Main();
};
init();
and
Main.js
export default class Main {
constructor() {
console.timeEnd('time until constructor called');
}
}
Running this code in Chrome 65 (On a Mac)
I get the following output:
Run 1
load module: 0.141845703125ms
time until constructor called: 7.90087890625ms
Run 2
load module: 0.139892578125ms
time until constructor called: 6.5498046875ms
Run 3
load module: 0.160888671875ms
time until constructor called: 7.14404296875ms
Run 4
load module: 0.297119140625ms
time until constructor called: 7.4228515625ms
My download times ranged between 2ms and 10ms for each of the three files.
I really can't tell why your times are so much slower. But they should not be. Maybe your server is getting hammered and unable to respond fast enough?
Possible things to check:
What happens if you try to download each of the files from the address bar? Do they still take forever to download?
What about on a different server?
I was was having the same problem when serving my files using:
python -m SimpleHTTPServer
After changing to use python3 http.server instead it fixed the problem:
python3 -m http.server
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 website with Webpack 5, html-webpack-plugin, and html-loader.
Here's my index.html:
<!DOCTYPE html>
<html>
<head>
<title>test page</title>
</head>
<body>
<p>hello there</p>
<script type="application/javascript" src="../script/index.ts">
</script>
</body>
</html>
Here's my index.ts:
console.log('hi');
document.body.append('this isnt hmr but its not bad for a static site generator');
document.body.append('ree');
Here's the relevant section of my webpack.config.js:
module.exports = async (env) => {
return {
// ...
module: {
rules: [
// ...
{
test: /\.html$/i,
use: ['html-loader'],
},
],
},
plugins: [
// ...
new HtmlPlugin({
template: '../path/to/index.html',
filename: 'index.html',
})
],
// ...
};
};
When I try to compile this, I get the following error:
ERROR in Error: webpack-internal:///608:2
document.body.append('this isnt hmr but its not bad for a static site generator');
^
ReferenceError: document is not defined
- 608:2 eval
webpack-internal:///608:2:1
- index.html:21 Object.608
/home/laptou/website/client/source/page/index.html:21:1
- index.html:71 __webpack_require__
/home/laptou/website/client/source/page/index.html:71:41
- 673:3 eval
webpack-internal:///673:3:34
- index.html:48 Object.673
/home/laptou/website/client/source/page/index.html:48:1
- index.html:71 __webpack_require__
/home/laptou/website/client/source/page/index.html:71:41
- index.html:81
/home/laptou/website/client/source/page/index.html:81:18
- index.html:82
/home/laptou/website/client/source/page/index.html:82:12
- index.js:320 HtmlWebpackPlugin.evaluateCompilationResult
[client]/[html-webpack-plugin]/index.js:320:28
Why is the code in my index.ts being evaluated, instead of just being bundled, and how do I make this stop happening?
Edits:
I have looked at this question, but I feel my question is different because I am getting a different error. I already have a Babel loader in my chain, so all of the code should be perfectly digestible, plain JS.
I have looked at this question and its answer also, but I do not want to use Parcel because I could not get its glob imports to work correctly and consistently, and it does not have all of the features and community support that Webpack has.
I see a couple of issues in your webpack.config.js, and your index.html template.
Your template directly tries to include the index.ts, which is typescript.
But the plugin will inject the bundled script, so you shouldn't specify the script tag
yourself.
You have typescript in your project, but no rule specified with a loader for typescript.
You mention you are using 'html-webpack-plugin',
but the plugin you specify is spelled differently.
A final hint, on the error:
Whenever I've encountered 'docucument is not defined',
it has been because the webpack loader rules were configured inconsistently,
which causes webpack to execute the loaders on the wrong kinds of input,
which leads to weird 'the world is not defined!' kinds of errors.
Otherwise 'document is not defined' happens when clientside typescript/javascript
is erroneously included in a SSR(server-side-rendering) and/or nodeJS/server-side context.
today i was working on a project, and i got this error.
Uncaught ReferenceError: launch is not defined
at HTMLInputElement.onclick (home.html:77)
i don't understand what i did wrong here..
Here is the index.js file:
function launch() {
console.log('test');
}
module.exports.launch = launch;
and home.html:
<script>
let func = require('./index');
let launch = func.launch();
document.getElementById('lanBTN').addEventListener('click', () => {
launch();
});
<input type="button" value="Launch!" id="lanBTN" onclick="launch()">
</script>
Any ideas why this is happening..?
Require is a commonjs module specification, it doesn't work on the browser unless you use some bundler like webpack or browserify to resolve the dependencies between all of you modules and bundles one single js file to include in your html
As #mehdi-belbal mentioned you can not use CommonJS in HTML files expect if when using module bundlers like Webpack.
Besides of that module.exports is useless here, try to link your javascript module in the head of the document. and the declared function after. that will attach to the window object and you can use them both by using window.func() and func()
<head>
<script src="./index.js"></script>
</head>
<body>
...
<script>
func();
</script>
</body>
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.
Trying to create an AMD Javascript library to be included in non-AMD projects. Here's my setup:
app.coffee
define ->
class App
constructor: -> console.log 'instantiating App'
init: -> console.log 'Init called'
index.html
<body>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="dev-latest.js"></script>
<script type="text/javascript">
$(document).ready(function(){
console.log('doc', window.app);
});
$(function(){
console.log('func', window.app);
});
window.onload = function()
{
console.log('onload', window.app);
}
</script></body>
main.js
require(['cs!app'], function(app){
return window.app = new app;
});
I am building this project with r.js optimizer to get dev-latest.js as the output. Here's my build file (PS: Build is successful):
({
baseUrl: './vendor',
paths: {
app: '../app',
'require-lib': 'require'
},
name: '../main',
out: 'dev-latest.js',
include: 'require-lib',
preserveLicenseComments: false
})
When running the code in the browser here's the output:
doc undefined
func undefined
onload undefined
instantiating App dev-latest.js:1
app.init(); // running this manually in the browser console
Init called
How should I go about this and get app to load before being used ?
Using AMD you cant rely on a module being created outside of a module. The only reliable way is to load the result of a module into another module. So in your case need to create a new module which then can lsiten to $.read:
define( [App], (App)->
$(document).ready(function(){
console.log('doc', App);
});
)
Solved it by using browserify (just found about it) which uses the CommonJS form of dependency loading and saves all that clutter. Also a great template for starting projects is amitayd's grunt-browserify-jasmine setup