NW.js + Babel: ES6 import working but not export? - javascript

I'm building a NW.js app, currently with babel-standalone and React. I can use ES6 import, but ES6 export on the other hand does not work, console spits out unexpected token export. What's going on?
index.html:
<html>
<head>
<meta charset="utf-8">
<script src="assets/react.min.js" charset="utf-8"></script>
<script src="assets/react-dom.min.js" charset="utf-8"></script>
<script src="assets/babel.min.js" charset="utf-8"></script>
</head>
<body>
<script type="text/babel" src="script/App.js"></script>
</body>
</html>
(yes, Babel indeed works, since React stuff inside runs OK)
In app.js:
import Lib from "./script/lib.js";
(and it's indeed exporting lib.js correctly, since that is the file responsible for the error)
In script/lib.js:
export default class {...};
I'm aware I can use Node modules instead, or even HTML script loading, but that's beside the point. I want to know why export doesn't work even if Babel doesn't seem to be broken, and even import works fine.

The problem is that Babel doesn't see files that were loaded via require, and they are loaded as they are, without transpilation.
There can be several ways to work this around, but the easiest one will be using Babel at build step.
Process your source code and then load processed code nw.js environment. The example how to do that you can find at this boilerplate project

Related

Importing ReactDOM doesn't render anything

I'm pretty new to React and I've been trying to set up a REACT app. However, I always get a blank page. Can anyone help?
HTML Code (index.html)
<html>
<head>
<meta charset="UTF-8" />
<title>Home</title>
</head>
<body>
<div id="root"></div>
<script src="index.js" type="text/babel"></script>
</body>
</html>
Javascript (index.js)
import React from "react"
import ReactDOM from "react-dom"
const page = (
<div>
<h1>My page</h1>
</div>
)
ReactDOM.render(page, document.getElementById("root"));
And yes, I am using a live server to run this code.
Browsers don't understand the text/babel MIME type.
It is there for Babel to search the DOM for scripts that it should process to convert from whatever they are (JS + JSX in this case) to JS.
You haven't included Babel in your page though.
You have a further problem in that inside your script you have import statements which depend on Node.js module resolution (and you're using a browser, not Node).
You should start at the beginning of the React guide.
You currently have an odd mix of about 20% of the quick guide to adding React to a website and 5% of using a Node.js based toolchain to transpile your code.
I recommend starting with create-react-app as it gives you a robust, performant foundation to get started with.

Adding react to static html

I would like to add a React component in one of the divs from a static HTML page. I'm doing so instead of converting the entire page into React since I only need React for few parts of my web page. I followed the instructions on https://reactjs.org/docs/add-react-to-a-website.html. And my questions are:
Is it okay to do that, or is it rather recommended that I implement my website entirely in React?
I did what the aforementioned page told me, but the section I used React did not get implemented when I displayed it on my browser (my IDE is WebStorm). Is there a specific script (like yarn start when using React framework) that I have to run in order to compile?
Checkout this minimal example. You need to include 3 scripts
react.development.js (the react lib)
react-dom.development.js (react lib to interact with dom)
babel.min.js (converts react JSX into browser compatible JS)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function HelloWorld(props){
return <h1>{`Hello, world! ${props.name}`}</h1>;
}
ReactDOM.render(
<HelloWorld name="James"/>,
document.getElementById('root')
);
</script>
</body>
</html>
Note: this is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Read this section for a production-ready setup with JSX:
https://reactjs.org/docs/add-react-to-a-website.html#add-jsx-to-a-project
In a larger project, you can use an integrated toolchain that
includes JSX instead:
https://reactjs.org/docs/create-a-new-react-app.html
You can also use React without JSX, in which case you can remove
Babel: https://reactjs.org/docs/react-without-jsx.html
SOURCE : https://raw.githubusercontent.com/reactjs/reactjs.org/master/static/html/single-file-example.html
Yes, it's ok. No, your entire website doesn't need to use React.
It should work as described in the tutorial you linked, you don't need to compile anything. The scripts invoked by yarn or npm in frontend projects usually bundle javascript modules together and transpile (we don't call it compiling since there is no machine code as output) from a modern version of EcmaScript into an older, established version of EcmaScript that is understood by most browsers. But for your small example, none of this really matters. In order to identify why your code doesn't work, it would be helpful to see it.

ES module import not working

I am trying to make simple example of vanilla ES import export.
index.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="module" src="main.js"></script>
</head>
<body>
</body>
</html>
main.js
import {foo} from './mathModule';
console.log(foo);
mathModule.js
export const foo = Math.sqrt(2);
when I run this page I get an error
main.js:1 GET http://[page].net/test/mathModule 404 (Not Found)
EDIT:
project structure
test
index.html
main.js
mathModule.js
import needs a fully qualified URL. You can't leave off the extension unless the absolute URL doesn't have an extension on it.
So judging by your examples use:
import {foo} from './mathModule.js';
As Nimeshka Srimal caught, it looks like the extension requirement varies between implementations. Firefox is appending .js automatically, but Chrome and Safari expect the actual address.
I'm looking at the spec, 15.2.2 Imports, and there doesn't seem to be any specification on whether the implementer should append the extension automatically or not.
Additionally, as ASDFGerte pointed out from the MDN docs on import:
The module to import from. This is often a relative or absolute path
name to the .js file containing the module. Certain bundlers may
permit or require the use of the extension; check your environment.
Only single quotes and double quotes Strings are allowed.
The simplest would be to remove the export and import expressions since you're already including both files in your html.
const foo = Math.sqrt(2) // mathModule.js
console.log(foo) // main.js
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script src="mathmodule.js"></script>
<script src="main.js"></script>
</head>
<body>
</body>
</html>
If you are using node or something similar to run the script, maybe you should use a transpiler such as babel. Import and Export are "new" javascript features hence they're not implemented in most browsers

Integrate React into existing Node express app using CDN

I'm creating a web app using node and react. Rather than seperate Node and React apps I want to integrate React into it. So rather than a react app, I tried importing react CDN into the index.html. My server serves the index.html perfectly, but I'm getting an error in the react component.
this is my index.html
<html>
<head>
<meta charset="utf-8">
<title>React Powered chat App</title>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js" charset="utf-8"></script>
<script src="/scripts/main.js" charset="utf-8"></script>
<body>
Hello !
<div id ='App'></div>
</body>
</html>
and this is my main.js
class App extends React.Component {
render(){
return (
<div>
Hello !
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('App'));
The error I'm getting is
Uncaught SyntaxError: Unexpected token < main.js:4
What have I done wrong? Isn't it possible to use react with CDN ?
And first when I used react/cjs/react.development libraries I got more errors. Then after reading this stackoverflow question I use /react/umd/ libraries. So what's the difference between cjs and umd CDN libraries ?
The code doesn't work because react uses JSX (HTML inside javascript), which cannot be read by the browser and needs to be transpiled to ordinary javascript which can be read by browsers. One such transpiler is babel. Your code doesn't work due to the absence of transpiler.
You can use create-react-app, which comes bundled with the transpiler and everything that you'll need to get started with react. And as I understand, since you want to add your express backend, here is a tutorial that will help you get started with attaching create-react-app to your express backend. Hope this helps.
Since JSX (the HTML code sprinkled in the JavaScript) is not regular JavaScript or ES6 code, you cannot load it directly in your browser.
So the problem is not getting the React library from a CDN, that’s fine.
The problem is that you have to transpile your main.js file to regular JavaScript code, for example using Babel.
The most commonly used tool to do this transpilation with Babel automatically is webpack.
If you don’t want to learn how to set up webpack and Babel in detail, I recommend to use create-react-app, this takes the burden of setting up all of the boilerplate from your shoulders and creates a JavaScript bundle that you can use directly in your browser.
Note: if you do end up using create-react-app, you don’t need to get the React lib from a CDN, it will already be included in the bundle.
You also need to add babel cdn in the Html file which would convert JSX to JS
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>

Splitting up React components into multiple files

I have only been learning React in a week so I am new to it and I am trying to write a simple todo app.
Originally I wrote all of the components in one file and loaded that file into the HTML file and it worked great. Now I am refactoring and trying to split the components into different files.
My full code is on my Github https://github.com/yasgreen93/todolist-react on the extracting-files branch.
I have split up each component into different files and have an linked them in script tags into my HTML. This is what my HTML file looks like:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Todo List</title>
<link rel="stylesheet" href="css/styles.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.16/browser.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel" src="scripts/components/TodoListApp.js"> </script>
<script type="text/babel" src="scripts/components/CompleteTodo.js"></script>
<script type="text/babel" src="scripts/components/TodoList.js"></script>
<script type="text/babel" src="scripts/components/SingleTodo.js"></script>
<script type="text/babel" src="scripts/components/AddTodo.js"></script>
<script type="text/babel" src="scripts/components/CompleteTodoButton.js"></script>
<script type="text/babel">
ReactDOM.render(
<TodoListApp url="/api/todos" updateUrl="/api/todos/update" pollInterval={2000}/>,
document.getElementById('container')
);
</script>
</body>
</html>
In the console, I always get the error message Uncaught ReferenceError: TodoListApp is not defined. I have tried loading them in different orders with no success. I have also watched many videos where they do very similar approaches without using webpack and it works for them. I would like to get this working first without using webpack and then move on to learning that.
Can anyone see where I am going wrong?
You have to add your components to a global window variable in order to use them in html script tag. Like window.TodoListApp =.... var declaration is relative to a file in which you declare it.
But it is considered to be a bad practice to expose parts of you code to a global scope and to transpile JSX in the browser. Instead you should consider to use some building system like Webpack.
This way you would be able to use es2015 import syntax to import components from one file to another, bundle everything in one file and much more additional benefits like code minification, sourcemaps, livereload etc.
Setting up React for ES6 with Webpack and Babel
Using React with Webpack Tutorial

Categories