First off, I'm very new to this Node.js world, so please bear with me for my noobishness. I'm currently getting my hands dirty on Node.js + Express + React + Webpack stack. I managed to run some code in development, but unable to run in production. I got the following error when I try to run node server.js on the terminal.
Nicholass-MacBook-Pro:sevva-backend nicholaslie$ node server.js
/Users/nicholaslie/Documents/Sevva/sevva-backend/server.js:7
import React from 'react'
^^^^^^
SyntaxError: Unexpected token import
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:545:28)
at Object.Module._extensions..js (module.js:582:10)
at Module.load (module.js:490:32)
at tryModuleLoad (module.js:449:12)
at Function.Module._load (module.js:441:3)
at Module.runMain (module.js:607:10)
at run (bootstrap_node.js:382:7)
at startup (bootstrap_node.js:137:9)
at bootstrap_node.js:497:3
However, in my local machine (development environment), I can run this just fine with npm start.
Nicholass-MacBook-Pro:sevva-backend nicholaslie$ npm start
> sevva-backend@0.0.1 start /Users/nicholaslie/Documents/Sevva/sevva-backend
> if-env NODE_ENV=production && npm run start:prod || npm run start:dev
> sevva-backend@0.0.1 start:dev /Users/nicholaslie/Documents/Sevva/sevva-backend
> webpack-dev-server --progress --profile --colors --inline --content-base public --history-api-fallback
70% 1/1 build modules http://127.0.0.1:3000/
webpack result is served from /
content is served from /Users/nicholaslie/Documents/Sevva/sevva-backend/public
404s will fallback to /index.html
3076ms build modules
8ms seal
6ms optimize
10ms hashing
30ms create chunk assets
23ms additional chunk assets
57ms optimize chunk assets
77ms optimize assets
20ms emit
When I go to http://localhost:3000, my page loads up as follows.
package.json:
{
"name": "sevva-backend",
"version": "0.0.1",
"private": true,
"main": "server.js",
"scripts": {
"build": "if-env NODE_ENV=production build:prod || build:dev",
"build:prod": "babel -d ./src ./public/bundle.js -s && webpack --config webpack.production.config.js",
"build:dev": "webpack",
"lint": "eslint src",
"start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
"start:dev": "webpack-dev-server --progress --profile --colors --inline --content-base public --history-api-fallback",
"start:prod": "webpack --config webpack.production.config.js && node server.js",
"test": "NODE_ENV=test mocha --recursive test",
"test:coverage": "nyc npm test",
"test:unit": "mocha --recursive test/middleware test/models test/routes",
"test:integration": "mocha --recursive test/integration"
},
"dependencies": {
"babel": "^6.5.2",
"babel-cli": "^6.18.0",
"babel-core": "^6.18.2",
"babel-eslint": "^7.1.0",
"babel-loader": "^6.2.7",
"babel-plugin-css-modules-transform": "^1.1.0",
"babel-plugin-transform-class-properties": "^6.18.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-es2015-modules-commonjs": "^6.18.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"babel-register": "^6.18.0",
"babel-runtime": "^6.18.0",
"body-parser": "^1.13.3",
"compression": "^1.6.2",
"cookie-parser": "^1.3.3",
"css-loader": "^0.25.0",
"eslint": "^3.9.1",
"express": "^4.14.0",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"firebase": "^3.5.3",
"glob": "^6.0.4",
"html-webpack-plugin": "^2.24.1",
"if-env": "^1.0.0",
"ignore-styles": "^5.0.1",
"jade": "^1.11.0",
"method-override": "^2.3.0",
"morgan": "^1.6.1",
"node-sass": "^3.11.2",
"path": "^0.12.7",
"postcss-loader": "^1.1.0",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-hot-loader": "^3.0.0-beta.6",
"react-router": "^3.0.0",
"react-tools": "^0.13.3",
"react-transform": "0.0.3",
"sass-loader": "^4.0.2",
"serve-favicon": "^2.3.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.3",
"webpack-cleanup-plugin": "^0.4.1",
"webpack-dev-middleware": "^1.8.4",
"webpack-dev-server": "^1.16.2",
"webpack-hot-middleware": "^2.13.1"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-eslint": "^7.1.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"chai": "^3.5.0",
"debug": "^2.2.0",
"eslint": "^3.9.1",
"eslint-plugin-react": "^6.6.0",
"mocha": "^3.0.2",
"nyc": "^8.1.0",
"request": "^2.60.0",
"supertest": "^2.0.0",
"time-grunt": "^1.2.1"
},
"engines": {
"node": "6.6.0"
}
}
Mind me for much of the unnecessary dependencies above. I'm very curious as to why webpack-dev-server works perfectly but not with node server.js, as seen in the file above.
Right now I've been scratching my head for hours trying to make sense of this issue. First off, I'm very aware that that ES6 import statements doesn't seem to work with the node command.
So, what I did was I tried to use babel-node instead. However, I can't also get it to work as I expect it to, it returns the following errors.
Nicholass-MacBook-Pro:sevva-backend nicholaslie$ babel-node server.js
/Users/nicholaslie/Documents/Sevva/sevva-backend/node_modules/bootstrap/dist/css/bootstrap.min.css:6
*//*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}im
SyntaxError: Unexpected token {
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:545:28)
at Module._extensions..js (module.js:582:10)
at Object.require.extensions.(anonymous function) [as .js] (/Users/nicholaslie/.nvm/versions/node/v7.0.0/lib/node_modules/babel-cli/node_modules/babel-register/lib/node.js:152:7)
at Module.load (module.js:490:32)
at tryModuleLoad (module.js:449:12)
at Function.Module._load (module.js:441:3)
at Module.require (module.js:500:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/nicholaslie/Documents/Sevva/sevva-backend/src/app.jsx:1:1)
Somehow, the babel-node also doesn't work as expected, as it fails on transpiling CSS files. My app.jsx file is as follows:
import 'bootstrap/dist/css/bootstrap.min.css'
import styles from './stylesheets/index.scss'
import navlinkStyles from './stylesheets/components/_navlink.scss'
import React from 'react'
import { IndexLink } from 'react-router'
import NavLink from './components/NavLink'
import Home from './components/Home'
export default class App extends React.Component {
render() {
return (
<div>
{this.props.children || <Home />}
<h1>It Works!</h1>
<p>This React project just works including <span className={styles.blueBg}>module</span> local styles.</p>
<p>Global bootstrap css import works too as you can see on the following button.</p>
<p><a className="btn btn-primary btn-lg">Enjoy!</a></p>
<ul role="nav">
<li><IndexLink to="/" activeClassName={navlinkStyles.navlinkActive}>Home</IndexLink></li>
<li><NavLink to="/about">About</NavLink></li>
<li><NavLink to="/repos">Repos</NavLink></li>
</ul>
{/* add this */}
{this.props.children}
</div>
)
}
}
As a side note, I'm aware that babel-node shouldn't be use for production. As it is said in the docs:
Not meant for production use You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly.
My webpack.config.js file:
"use strict";
var webpack = require('webpack');
var path = require('path');
var loaders = require('./webpack.loaders');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const HOST = process.env.HOST || "127.0.0.1";
const PORT = process.env.PORT || "3000";
module.exports = {
entry: [
'react-hot-loader/patch',
'./src/index.jsx' // your app's entry point
],
externals: {React: 'react'},
devtool: process.env.WEBPACK_DEVTOOL || 'cheap-module-source-map',
output: {
path: 'public',
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [{
// global css
test: /\.css$/,
exclude: /[\/\\]src[\/\\]/,
loaders: [
'style?sourceMap',
'css'
]
}, {
// local scss modules
test: /\.scss$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'postcss',
'sass'
]
}, {
// local css modules
test: /\.css$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
]
}, {
//JS/JSX files
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loaders: ['react-hot-loader/webpack', 'babel?presets[]=es2015,presets[]=stage-0,presets[]=react,plugins[]=transform-runtime']
}]
},
sassLoader: {
includePaths: [path.resolve(__dirname, "./some-folder")]
},
devServer: {
contentBase: "./public",
// do not print bundle build stats
noInfo: true,
// enable HMR
hot: true,
// embed the webpack-dev-server runtime into the bundle
inline: true,
// serve index.html in place of 404 responses to allow HTML5 history
historyApiFallback: true,
port: PORT,
host: HOST
},
plugins: process.env.NODE_ENV === 'production' ? [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
] : [
new webpack.NoErrorsPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
]
};
My webpack.production.config.js file:
var fs = require('fs')
var webpack = require('webpack');
var path = require('path');
var loaders = require('./webpack.loaders');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var WebpackCleanupPlugin = require('webpack-cleanup-plugin');
module.exports = {
entry: [
'./src/index.jsx'
],
// keep node_module paths out of the bundle
externals: fs.readdirSync(path.resolve(__dirname, 'node_modules')).concat([
'react-dom/server', 'react/addons',
]).reduce(function (ext, mod) {
ext[mod] = 'commonjs ' + mod
return ext
}, { React: 'react' }),
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [{
//local css modules
test: /[\/\\]src[\/\\].*\.css/,
exclude: /(node_modules|bower_components|public)/,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
}, {
//local scss modules
test: /[\/\\]src[\/\\].*\.scss/,
exclude: /(node_modules|bower_components|public)/,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass')
}, {
//global css files
test: /[\/\\](node_modules|global)[\/\\].*\.css$/,
loader: ExtractTextPlugin.extract('style', 'css')
}, {
//JS/JSX files
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loaders: ['react-hot-loader/webpack', 'babel?presets[]=es2015,presets[]=stage-0,presets[]=react,plugins[]=transform-runtime']
}]
},
node: {
__filename: true,
__dirname: true
},
plugins: [
new WebpackCleanupPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
drop_console: true,
drop_debugger: true
}
}),
new webpack.optimize.OccurenceOrderPlugin(),
new ExtractTextPlugin('[contenthash].css', {
allChunks: true
}),
new HtmlWebpackPlugin({
template: './src/index.html',
title: 'Webpack App'
}),
new webpack.optimize.DedupePlugin()
]
};
My objective: deploy this app in production. What is the correct command to run my app on the server, and what are the needed necessary changes? Hopefully someone can help :(