ReactJS - Unable to run babel code without serving HTTP files - javascript

I am new to reactjs and trying to install babel to run babel code without serving HTTP file. By following the Package Manager I have installed it with browserify as:
$ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify ] main.js -o bundle.js
After it I created the file .babelrc in the same root directory with following code
{ "presets": ["react"] }
And removed the HTTP babel-core source file as:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React Tutorial</title>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<!-- removed https://npmcdn.com/babel-core#5.8.38/browser.min.js -->
</head>
<body>
<div id="content"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('content')
);
</script>
</body>
</html>
but when I access it from http://localhost/react/ this doesn't work.

You haven't included the code that's failing or the error message, so this is a guess.
The problem is that when you run browserify, it transpiles (converts) the code you specify from ES2015 to plain old Javascript. So, when you do this:
browserify -t [ babelify ] main.js -o bundle.js
You're converting the code in main.js and writing it to bundle.js.
So there are two problems with your code:
you never include bundle.js in your HTML file. You need to add <script src="build/bundle.js"></script> to load the code that you transpiled.
the code in your HTML <script> block is not touched by browserify. Your build step (running browserify) is working on scripts, not on HTML files. So that code never gets transpiled and fails when the browser tries to execute it.
The reason it works when you include babel-core in the HTML is because Babel has a special "live" transpilation mode which will transpile your code when the page is loaded, and this mode DOES get the code in the <script> block because it's all running on the user's browser.

Related

How does Typescript know where dist/index.js is, if it doesn't exist?

There is something I don't understand about this. I am trying to learn Typescript and I got me this boilerplate code using Snowpack and it contains an index.html file which refers to "dist/index.js" as its script, look below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Web site created using create-snowpack-app" />
<link rel="stylesheet" type="text/css" href="/index.css" />
<title>Snowpack App</title>
</head>
<body>
<img id="img" src="/logo.svg" />
<canvas id="canvas"></canvas>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/dist/index.js"></script>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
This index.html thing is in the "public" folder. I also have "index.ts" file in the "src" folder, which only does a console.log("hello is this typescript or javascript idk"). It does give me this console log so it seems to be working.
What I don't understand is how the index.html tries to look for a folder "dist" containing a "index.js" file while neither the "dist" folder nor the "index.js" file exist. I also have a node_modules folder but it doesn't exist there either.
How does this work? Is the "dist" folder simulated or something, while containing a non-existing index.js file when this whole thing is running?
Typescript itself doesn't know except that when you compile all your other js files the compiler (babel/webpack etc.) will generate a dist/index.js file.
Basically it's like compiling your C++ file to build Google Chrome. C++ does not know where or what the chrome.exe file is except that the build script/command tells it to generate chrome.exe from source code.
Note: Depending on your build process the directory can be named dist or build or target or mootdrafters_website etc. The react-create-app script for example does not name it's output folder dist but generates build/index.js instead.
How did you run your boilerplate code, by using cmd 'snowpack dev'?
If so, snowpack provides a web server running in nodejs process, and the 'src/index.ts' has been transpiled to 'dist/index.js' (in memory).When your browser requests 'dist/index.js' , the snowpack server responses the file content in memory.That's why there is no such 'dist' folder.
More futher, if you try cmd 'snowpack build', you will see the 'dist' folder.
'snowpack dev' for development, using a web server locally
'snowpack build' for production, you can deploy the 'dist' folder to any other web servers

Uncaught SyntaxError: Unexpected token in import React from 'react'

I used to write a react app by using create-react-app and there was no problem. However, I tried to make a small app using only index.html and app.js. Errors were raised in Chrome to import and JSX. For import, Uncaught SyntaxError: Unexpected tokenFor JSX, Uncaught SyntaxError: Unexpected token <Is it because I did not install BABEL or ES6.
I tried to install babel but it still did not work. I also tried adding type="text/babel"
index.html
<!Doctype html>
<html>
<head>
<title>Social Card</title>
<meta charset="utf-8" />
</head>
<body>
<h1>content fahafafafaddha</h1>
<div id="root">
</div>
<script src= "app.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
</body>
</html>
app.js
import React from 'react'
import ReactDOM from 'react-dom'
ReactDOM.render(
<h1> Hello</h1>,
document.getElementById('root')
)
The error is definitely because your code has not been transpiled (which is what babel does). You say that you installed babel..what do you mean by that? You need to configure babel so that it transpiles your code before you run it. create-react-app does it for you by using webpack to transpile, bundle and minify your code.
If you want to learn more about the specifics of how things are working and how to configure your app, Create a new create-react-app, and then run
npm run eject
This will eject all of the previously hidden configurations and help you understand how things are functioning.
UPDATE
One thing you can try is to inst all babel-cli with
npm install --save-dev #babel/core #babel/cli
and then you can use it like
npx babel app.js --out-file app-compiled.js
and use app-compiled to run the server.
UPDATE 2
You are using ES6 syntax (the import statements) as well as JSX (using HTML-ish code in a javascript file). This code cannot be compiled directly by a JS compiler and that's why it's showing you the above error. In order to fix this you need to transpile it into JS that can be read by the browser. There are several ways to do that, some of which are:
Use webpack to transpile, minify, bundle and inject your code into your html.
Use babel-cli to transpile your code manually, and then import the transpiled file instead
Use babel standalone as is explained here
As for what I meant by use app-compiled, I meant include the output file from the babel-cli command (app-compile.js if you ran the command i wrote above) in your html instead of app.js
The order of your <script> tags is important. They are loaded in the order they appear. So your app.js must come after babel and react:
<div id="root"></div>
<!-- DEPENDENCIES MUST COME FIRST -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<!-- Your scripts -->
<script type="text/babel">
const App = () => <h1>Hello React!</h1>;
ReactDOM.render(<App />, document.getElementById('root'));
</script>
Next you can't use import statements when including your dependencies only with script tags. They will simply be available in global namespace. You could maybe use modules too when specifying the type="module" attribute on the script tags but that feature was only fairly recently added and may not be supported by a percentage of currently used browser versions.

what are .esm.js files and whats with the format: 'es' in rollup.js?

I was just going through this library HERE (glide.js) , as i was checking the package.json file i see the following command under the key scripts:
"build:esm": "rollup --config build/esm.js && rollup --config build/esm.modular.js",
What exactly is this script doing ? I know a a config file is being passed to rollup.js here, but whats with the .esm ? when i see the dist/ folder i also see a glide.esm.js file , what exactly is this file doing ?
The build config file for esm looks like below:
import build from './build'
export default Object.assign(build, {
input: 'entry/entry-complete.js',
output: Object.assign(build.output, {
file: 'dist/glide.esm.js',
format: 'es'
})
})
But i don't quite understand what the format: 'es' really means here. Basically to break it down , what is the difference between the glide.js and the glide.esm.js file in the dist/ folder ?
format: 'es' tells rollup that it should output the bundle in an ECMAScript Module aware way. This means that it should create a bundle that can be imported using something along the lines of:
import Glide from "some/place/glide/is/hosted/glide.js
If the context that this script is used in is not ESM aware, you will get syntax errors. In that case, it makes more sense to use a UMD rollup bundle because it is the most compatible version of the bundle.
Explaining UMD in depth is beyond the scope of this question, but suffice it to say that it makes the bundle able to work with AMD and CommonJS aware loaders as well as populating a global namespace with the bundle's exports.
Additionally, for browsers that do not understand what ES modules are or would throw syntax errors if they tried to parse them, you can include a fallback script that would leverage the UMD or bundle of another format using a script of form: <script src="some/non/esm/script.js" nomodule="true" /> which would tell an ESM aware context that it shouldn't run the linked script.
Concrete Example
Consider the following snippet which should work in Firefox and Chrome since they support ESM modules. Stack Overflow snippets do not have a way to load modules so you will need to put together a small project using the following code:
demo.js
import Glide from "https://unpkg.com/#glidejs/glide#3.2.3/dist/glide.esm.js";
new Glide(".glide").mount();
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Module Demo</title>
<link rel="stylesheet" href="https://unpkg.com/#glidejs/glide#3.2.3/dist/css/glide.core.min.css" />
<link rel="stylesheet" href="https://unpkg.com/#glidejs/glide#3.2.3/dist/css/glide.theme.min.css" />
<script type="module" src="demo.js"></script>
</head>
<body>
<main>
<div class="glide">
<div data-glide-el="track" class="glide__track">
<ul class="glide__slides">
<li class="glide__slide">Foo</li>
<li class="glide__slide">Bar</li>
<li class="glide__slide">Fizz</li>
</ul>
</div>
</div>
</main>
</body>
</html>

run npm scripts to deploy to s3

I have a simple express app which renders some config for the client bundle to use:
const config = config.get('client');
const HTML = `
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="client"></div>
<script>
window.config = ${JSON.stringify(config)}
</script>
<script src="/bundle.js"></script>
</body>
</html>
`;
res.status(200).send(HTML);
For production I want to host a static version of this on AWS s3. I want a static version of the html above with both the stringified config and the webpack bundle.js including the hash.
For this I think I need a small express server that pulls in a templated version of the html above which will get populated with the config and the webpack bundle name and then written as index.html in the dist folder.
I intend this script to be run from an npm script:
scripts: {
build-html: node render-static.js,
},
Once this has run the next step would be to upload it to an s3 bucket so that would require another node script that would need to run. I might end up with a final npm run deploy that runs:
npm run build-html && npm run-deploy-static
I'm not sure if there is a better / more accepted way of doing this sort of thing? Is it correct to be running two node scripts in order to be deploying a part of my app?

Load font-awesome with jspm

I started investigating jspm and stumbled across this issue.
I seriously search all over Google but could not find a simple answer or example.
How do you load CSS and fonts that come with it?
I tried to do <script>System.import('font-awesome/css/font-awesome.css')</script> but it does not work. It adds .js extension to the url and I get a 404. like this: font-awesome.css.js
I tried import 'font-awesome/css/font-awesome.css'; which does not work either.
So, for a jspm packages that contain css and fonts, how do you make them available to my application?
And what about the font files? Do I have to move them manually or get gulp to do it? How do you handle this in your jspm workflow?
Thanks
EDIT
Based on the given answer by Joy, I just want to clarify what I want.
Investigating jspm I read about its ability to dynamically load modules (aka es6 module loading). This, I believe, is the crux of jspm. I don't want to bundler every time I change a file! I want to bundle once at the end of the development just before I upload the app to the server. During the development cycle I want jspm to dynamically load my js modules and assets. Otherwise, if bundling is required, I can just use already available (and much faster bundling solutions) like Browseryfy, Webpack. So bundling at every file change is not a solution. With Systemjs and HTTP/2 we should not need to bundle at all ever. And this, I thought, what the jspm was all about.
So can someone tell me if it is possibly to load assets (css, fonts, images) dynamically with jspm the same way it loads js modules? The key word here is dynamically without bundling first. If yes - how?
Before you using font-awesome package, you need the CSS loading plugin and CSS build support.
$ jspm install css
$ jspm install npm:clean-css --dev
$ jspm install font-awesome
And create the main.js file which contains:
import 'font-awesome/css/font-awesome.min.css!';
Until now, you have two options that make them available.
(1) The first solution in index.html file is
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.import('main');
</script>
<i class="fa fa-camera-retro"></i> fa-camera-retro
</body>
</html>
You don't need to bundle all js file here. Import the main.js file only.
(2) Second solution is use jspm bundle-sfx
You can build a build.js by
$ jspm bundle-sfx main.js ./build.js
or gulp to automatically build the bundle file.
Here is a simple gulpfile.js example:
const gulp = require('gulp');
const gulp_jspm = require('gulp-jspm');
const paths = {
main: './main.js',
dest: './dest/'
};
gulp.task('scripts', function () {
gulp.src(paths.main)
.pipe(gulp_jspm({
selfExecutingBundle: true
}))
.pipe(gulp.dest(paths.dest));
});
function reportChange(event){
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
}
gulp.task('watch', function () {
gulp.watch([paths.main], ['scripts']).on('change', reportChange);
});
gulp.task('default', ['watch', 'scripts']);
Now, create a index.html file and can test it by httpster
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="./dest/main.bundle.js"></script>
<i class="fa fa-camera-retro"></i> fa-camera-retro
</body>
</html>
Check the jspm-cli/docs/plugins.md to get more informations.
load it with css plugin.
jspm install css
jspm install fontawsome=github:FortAwesome/Font-Awesome
in the js file
import fontawsome from 'fontawsome/css/font-awesome.css!';

Categories