I want to use ES6 for my next project and I'm using Traceur as transpiler for the purpose. I got it working the way described in the Getting Started guide. However I would like to compile all my source files into single minified file in a way they describe it on the Compiling Offline page. But I cannot get it to work with multiple source files organized in a nested directory structure.
Here's a sample project to explain the problem. It has index.html in root folder and two .js files under src.
<project-root>
/index.html
/src/one.js
/src/two.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="traceur.js" type="text/javascript"></script>
<script src="bootstrap.js" type="text/javascript"></script>
<script type="module" src="src/two.js"></script>
<script type="module">
import Two from 'src/two.js';
let t = new Two();
console.log(t);
</script>
<title>Title</title>
</head>
<body>
</body>
</html>
src/one.js
export default class One {
constructor() {
console.log("One constructor");
}
}
src/two.js
import One from 'src/one.js';
export default class Two extends One {
constructor () {
console.log("Two constructor");
super();
}
}
As I said, if I open index.html in browser, it will correctly work, printing the instance of Two to console.
But when I try to compile this offline, I get following error
PS D:\code\flattraceur> traceur.cmd src/two.js --out out\two.js
[Error: Error: ENOENT: no such file or directory, open 'D:\code\flattraceur\out\src\one.js'
Specified as src/one.js.
Imported by ../src/two.js.
Normalizes to src/one.js
locate resolved against base 'D:/code/flattraceur/out/'
]
As you can see, while compiling src/two.js, traceur looks for src/one.js under the output directory. I couldn't find any options on traceur that would let me customize the root of its search for referenced modules. I tried the --dir option too, but it fails too.
PS D:\code\flattraceur> traceur.cmd --dir src out
Error: At least one input file is needed
Any suggestions?
Related
I've got and exportUserList.js, importUserList.js and the main.js files. The main.js file contains already defined 2 variables which I want to log to the console and I also want to log the imported user variable from the main.js file. But I keep on receiving 'user not defined'. I've used the suggested window option, but it is not passing on the variable. Can this be corrected?
this is the html:
<html lang="en">
<head>
<meta charset="utf-8" />
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet" />
<title></title>
<style>
</style>
<head>
</head>
<body>
<script type="module" src="/importUserList.js"></script>
<script type="text/javascript" src="/main.js"></script>
</body>
this is the export exportUserList.js :
export const user = 'first user'
this is the import importUserList.js :
import {user} from './exportList.js'
console.log(user)
window.user = user
and this is the main.js:
let names = 'mark'
let numbers = 10
console.log(names)
console.log(numbers)
console.log(user)
Option 1: defer your main script, because modules defer by default, and so because your main script doesn't it gets runs before the module has.
However, that's the bad option, and you shouldn't put that into practice because that keeps you using modules in completely the wrong way. Never do that.
The much better solution is to make your main.js a module and then tell it to import what it needs in order to run. You don't load modules only to bind their data onto globalThis (window in this case), the whole point of modules is to keep code contained, so that whatever needs a module's exports, can just import that as needed. You use modules to not pollute the global scope =)
So: remove that importUserList.js and instead put the import in your main script:
import {user} from './exportList.js'
let names = 'mark'
let numbers = 10
console.log(names)
console.log(numbers)
console.log(user)
And then load your main script as a module with:
<script type="module" src="/main.js"></script>
And then of course remember that modules always load deferred.
Basically: if you're using modules, use modules "all the way down".
I seem to be going in circles trying to get a simple nested .js files to work. I start with these 2 files and it works as expected:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="module" src="./scripts/file1.js"></script>
<title>Hello World Page</title>
</head>
<body >
<div>
Some prompt: <input id="Xxx" onkeyup="file1Go('index.html calling file1Go()')"/><br />
</div>
</body>
</html>
file1.js
function file1Go(msg) {
alert('In file1.js - ' + msg);
}
Then I create a new file2.js and modify file1.js to import it. I also modify it to export the function that is used. I then also modify the index.html file's script tag to tell it that file1.js is now a module like this (to avoid the 'Cannot use import outside of a module' error):
<script type="module" src="./scripts/file1.js"></script>
Modified file1.js
import { file2Go } from "./file2.js"
export function file1Go(msg) {
alert('In file1.js - ' + msg);
file2Go(msg);
}
New file2.js
export function file2Go(msg) {
alert('In file2.js - ' + msg);
}
This results in the html page loading and both .js files downloading without error, but at runtime it fails to find the exported function in file1.js:
(index):11 Uncaught ReferenceError: file1Go is not defined at HTMLInputElement.onkeyup ((index):11)
That's it. What stupid thing am I doing wrong or what am I missing?
And thanks in advance for taking the time.
Afterthought: Putting similar .js files in a folder and executing with node.js appears to work.
More Info:
I've discovered that the following <script> tag does import and execute the function. I can also set HTML event handlers there. It's just that functions are apparently not visible outside of the scope of the <script> tag which to my little brain appears to be unduly restrictive and unuseful.
<script type="module">
import { file1Go } from "./scripts/file1.js";
file1Go("logging on start in <head> tag..."); // works
document.getElementById('Xxx').onkeyup = file1Go; // also works
</script>
Note: My endgame here is to use TypeScript which would have many files. I removed TypeScript from my repro for simplicity and to target the root cause of my issue. Once I understand the scoping issue I'll move on to TypeScript.
I'm trying to understand how to use modules in javascript.
But it seems that if I import a module, then I cannot log anything to console.
Here's my code:
index.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="js/scene.js" type="module"></script>
<script src="js/main.js" type="module"></script>
</body>
</html>
scene.js:
class Scene {
constructor() {
console.log("Scene created");
}
}
export default Scene;
main.js:
import { Scene } from './js/scene.js';
var scene = new Scene();
console.log("Hello World");
The Expected Result:
Scene created
Hello World
The Result I Get:
Nothing (No Result)
What is wrong with my code and how can I properly use a module?
I see 3 mistakes
in index.html the first script tag is useless.
import is relative to script file, not html.
Scene.js export a default value not a variable named Scene.
solutions:
import Scene from './scene.js';
or
remove default in Scene.js, and import {Scene} from './scene.js';
In your scenario, I believe that line 1 of main.js is throwing an error. In your index.html file, you're suggesting that you have a folder named js with both javascript modules in it; however, in the main.js file, you're suggesting that scene.js is at path js/js/scene.js.
You probably meant import { Scene } from './scene.js';.
You should open your browser's console to view any errors.
For example, if you are using Google Chrome, becoming familiar with the Chrome Devtools will be invaluable in allowing you to resolve bugs like this one by yourself in the future.
The Chrome Devtools console will allow you to view errors in your website, which will give you an immediate answer on what is wrong. In addition, setting breakpoints will allow you to step-through each line of code and trace the flow of executed lines of code and the value of variables at each point in time.
Learn more here: https://developers.google.com/web/tools/chrome-devtools/javascript
I'm literally just trying to get a simple Polymer 3 app with lit-element to work. From VS Code, I have run polymer serve, and when I navigate to localhost:8081 to my index.html, I get the error in F12 tools:
Uncaught TypeError: Failed to resolve module specifier "#polymer/polymer/lib/mixins/properties-mixin.js".Relative references must start with either "/", "./", or "../".
This is extremely frustrating and I've been trying to resolve this issue for quite a while.
In HTML, I am simply including the file as expected:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test Polymer 3</title>
<script type="module" src="./node_modules/#polymer/lit-element/lit-element.js"></script>
<script type="module" src="./MyApp.js"></script>
</head>
<body>
<my-app score='5'></my-app>
</body>
</html>
And in the JavaScript file for my custom element, I am doing the following:
import {LitElement, html} from './node_modules/#polymer/lit-element/lit-element.js';
class MyApp extends LitElement {
constructor() {
super();
}//end ctor
static get properties() {
return {
score: Number
}
}//end properties
//no get template needed. Use _render instead
_render({score}) {
return html`The score is ${score}`; //equivalent {{score}} or [[score]]
}//end _render window.customElements.define(MyApp.is, MyApp);
static get is() {
return 'my-app';
}//end is
}//end class
window.customElements.define(MyApp.is(), MyApp);
Any help would be greatly appreciated. I am very new to some of the Web component technology. I've used HTML5, CSS3, JavaScript, jQuery, etc. for a long time, but this new push for Web components and Polymer 3 is like a very different animal, and I'm having trouble grasping some aspects of the workflow.
I can't figure this out. I have a small app setup with an index.html that includes a javascript file. On the same directory as that file is another file named myJsModule.js with the following code:
export default class{
doStuff()
{
console.log("calling goStuff() from external Module");
}
}
The main javascript file that is loaded from the html then does the import in this way:
import myJsModule from "myJsModule";
// TESTING MODULES
let myNewModule = new myJsModule();
myNewModule.doStuff();
I have a local web server running using Node, so I'm accesing this index.hmtl through my localhost: http://127.0.0.1:8080.
Im getting the following error: Uncaught SyntaxError: Unexpected identifier (referring to myJsModule on my main js file). I also tried using babel to transpile this into previous javascript. I had the same problem using the "require".
Shouldn't my local server figure this out? Or am I using this wrong?
As of Chrome 61, modules are natively supported. I was able to get your example working with the following HTML and JavaScript.
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Native Module</title>
</head>
<body>
<p>Hello, world!</p>
<script type="module">
import MyJsModule from './MyJsModule.js';
let myJsModule = new MyJsModule();
myJsModule.doStuff();
</script>
</body>
</html>
MyJsModule.js:
export default class MyJsModule {
doStuff() {
console.log("calling doStuff() from external Module");
}
}