Can't access dynamic html using html-webpack-plugin with express server - node.js

Recently, I want to use html-webpack-plugin in my project, but face a problem.
Here is part of my server.js and webpack.dev.config.js
server.js
if (process.env.NODE_ENV === 'development')
{
const webpack = require('webpack');
const config = require('./webpack.development.config');
const compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler,
{
noInfo: true,
publicPath: '/'
}));
app.use(require('webpack-hot-middleware')(compiler));
}
app.get('*', (req, res) =>
{
res.sendFile(path.resolve(__dirname, 'public/asset','index.html'));
});
webpack.dev.js
plugins: [
new HtmlWebpackPlugin({
template: './public/enter.html',
filename: 'index.html'
}),
new PreloadWebpackPlugin()
]
I can access this directly like http://localhost:3000.
It's supposed to be accessed by any path e.g.http://localhost:3000/counter, but get
Error: ENOENT: no such file or directory, stat
'/Users/paulhuang/Documents/workspace/react-redux-template/public/asset/index.html'
I use npm run build to create a harddisk index.html, and solved the problem.
Any other better idea? Thanks!

Related

Cannot GET /path using ReactJS, webpack, express

I've tried almost every solution but I can't find any solution for this problem. I'm using express to render my ReactJS code, build with webpack. I can open pages without any issues until I'm being redirected from home page. But when I tried entering the URL on browser or refresh the page, I cannot see the page. Instead I see this error:
Cannot GET /path
I have also tried adding historyApiFallback: true to my webpack.config.js but no luck there.
Below are my scripts from package.json
{
...
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server --mode development --open",
"start": "npm run build && node server.js"
},
...
}
And this is my webpack.config.js:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require('path');
const htmlPlugin = new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
});
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
publicPath: '/',
},
devServer: {
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
]
},
plugins: [htmlPlugin],
resolve: {
extensions: ['*', '.js', '.jsx']
},
};
And the server.js file:
const path = require('path');
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.get('/', function(request, response) {
response.sendFile(__dirname + '/dist/index.html');
});
app.listen(PORT, error => (
error
? console.error(error)
: console.info(`Listening on port ${PORT}. Visit http://localhost:${PORT}/ in your browser.`)
));
Important NOTE
When I run server with npm run dev, there is no issues. I can enter URL manually and refresh the page.
But when I run server with npm run start, I am facing the issue I described above.
app.get('/', ... ); only sends back the index.html on the / path, you need to return it on every path
app.get('*', function(request, response) {
response.sendFile(__dirname + '/dist/index.html');
});

Webpack help - add hot loading and source mapping to a React / Node Project

I'm a webpack newbie. I'm trying to add React to a simple Node project but I've only ever used React with a pre set up webpack dev server and not with another server. Webpack runs it's own node server so this poses one problem for me.
Here's what I need help with:
How do I add hot loading and source mapping if I'm using Express?
How can I add a global Bootstrap css from my public folder with webpack to this project (is there a way to do that kinda of how I did this with the js files and html-webpack-plugin)?
I've tried using webpack's dev server to get get hot loading but I've run into the problem where I have two servers conflicting: webpack and app.js server.
Here's part of my app.js file
var app = module.exports = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
//API Routes
// all other requests
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
// Starting server
http.createServer(app).listen(port);
.babelrc
{
"presets": [
"react",
"es2015",
"stage-0"
]
}
webpack.config.babel
import webpack from 'webpack'
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: __dirname + '/public/index.html',
filename: 'index.html',
inject: 'body'
})
const base = {
entry: {
"jquery": __dirname + '/public/js/lib/jquery/jquery-2.0.3.min.js',
"bootstrap": __dirname + '/public/bootstrap/js/bootstrap.min.js',
"index": __dirname + '/app',
},
output: {
path: __dirname + '/dist',
filename: '[name].js',
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.css$/, loader: 'style!css?sourceMap&modules&localIdentName=[name]__[local]___[hash:base64:5]'}
]
},
}
const developmentConfig = {
devtool: 'cheap-module-inline-source-map',
plugins: [HTMLWebpackPluginConfig]
}
export default Object.assign({}, base, developmentConfig)
I tried adding new ExtractTextPlugin("dist/[name].css") to plugins and replacing my css loader with loader: ExtractTextPlugin.extract("style-loader", "css-loader") but I'm still not able to add bootstrap css or any css to my app.
Notice in your webpack.config.babel file you have this output:
output: {
path: __dirname + '/dist',
filename: '[name].js',
},
You need to put this [name].js file in your dist/index.html.
This blog post might be helpful for you for getting yourself properly set up!

Uncaught ReferenceError: global is not defined setting up node/express server and webpack

I'm trying to set up a very simple script that fetch's data from an API and consumes it's data. I need to use CORS, so I set up a node/express server and pointed it to my Webpack bundle. The error I am getting is global is not defined. From googling this I've seen people fix their problems by disabling react/redux tools which seemed to point at hot reloading. Problem is, I'm not using hot reloading.
After seeing that I looked into what I am using global which pointed at my fetch expression. However, removing all my fetch code didn't solve anything
My server looks like this
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const cors = require('cors');
const port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cors());
app.use(express.static(path.join(__dirname, '../dist')));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../index.html'));
});
app.listen(port, function(){
console.log('server running on http://127.0.0.1:' + port + '/');
});
and my webpack config looks like this
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: ['babel-polyfill', './scripts/app.js'],
target: "node",
output: { path: __dirname, filename: './dist/bundle.js' },
devtool: 'source-map',
module: {
loaders: [
{
test: /.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015'],
"plugins": ["transform-object-rest-spread"]
}
}
]
}
};
All i can think of now is that I didn't set up my express server correctly or I'm missing something in my webpack config.
Alright, The issue was being caused by placing babel-polyfill in my entry point in my webpack.config. As I already had a preset for ES2015 I didn't need the polyfill.
I am unsure as to why I had placed the babel-polyfill in my entry.

how to use ngnix to serve webpack build files in production

I wrote a vue + webpack project and it works fine in webpack-dev-middleware. Now I want to deploy it with nginx. What I do is write a webpack.build.config.js and bundle all files into a dist folder. Then I just copy the dist folder into nginx html folder and assign the index in nginx.conf. However, it has an error said:
[Vue warn]: Failed to mount component: template or render function not
defined. (found in root instance)
I am a newbie for devops/backend and quite confused with the overall build or deploy process. Is webpack-dev-server or nodejs still need in the production environment? My production environment backend is nginx/PHP and IIS/.Net, now it do not have node installed at all.
My nginx.conf is
location / {
root html/dist;
index index.html index.htm;
}
And the webpack.build.config.js is
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "components";
//var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');
module.exports = {
entry: [
path.join(__dirname,'./index.js')
],
output: {
path: path.join(__dirname, '/dist/'),
filename: '[name].js',
publicPath: '/'
},
devtool: 'eval-source-map',
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, 'index.html'),
inject: true
})
],
resolve: {
root: [path.resolve('./components')],
extensions: ['', '.js', '.css']
},
module: {
loaders: [
]
}
};
When build I run
webpack -p --config ./webpack.build.config.js
I'm using vue-cli to init vuejs webpack project. And the project already has build script, you can refer it:
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
After built, we will have a dist folder. Upload all files inside to html folder of Nginx (default)
Config root path to use full path like this:
listen 80;
server_name mydomain www.mydomain;
root /var/www/html;

webpack-dev-middleware and Express - can't get them to collaborate

I am trying to set up my first project using Webpack and Express but somehow I am doing something wrong.
This is what I did:
1. CREATED SAMPLE PROJECT
Created a sample project using express-generator. My folder structure is something like:
express-project
-app.js
-webpack.config.js
-public
-javascripts
-modules
-build
2. SET UP HANDLEBARS
Set up handlebars as view/template engine and created a couple of routes
3. WEBPACK CODE
Created the Webpack specific code/configuration as follows
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var webpackHotMiddleware = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false';
module.exports = {
resolve: {
alias: {
handlebars: path.resolve('public/vendor/handlebars-v4.0.5.js'),
bootstrap: path.resolve('public/vendor/bootstrap/js/bootstrap.js'),
pubsub: path.resolve('public/vendor/ba-tiny-pubsub.js')
}
},
context: path.resolve('public/javascripts'),
entry: {
cart: ['./modules/cart', webpackHotMiddleware],
index: ['./modules/products.js', webpackHotMiddleware],
vendor: ['bootstrap', 'pubsub', webpackHotMiddleware]
},
output: {
path: path.resolve('public/javascripts/build'),
publicPath: 'javascripts/build/',
filename: '[name].js',
chunkFilename: "[id].js"
},
module: {
loaders: [
// some loaders here
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
// some code before
var app = express();
(function() {
// Step 1: Create & configure a webpack compiler
var webpack = require('webpack');
var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : './webpack.config');
var compiler = webpack(webpackConfig);
// Step 2: Attach the dev middleware to the compiler & the server
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
}));
// Step 3: Attach the hot middleware to the compiler & the server
app.use(require("webpack-hot-middleware")(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}));
})();
// some code after
4. JS CODE ON TEMPLATE
Then on the handlebars page I require the bundled javascripts
<script src="javascripts/build/common.js"></script>
<script src="javascripts/build/vendor.js"></script>
<script src="javascripts/build/cart.js"></script>
5. NPM START
Finally if I start the server using the standard npm start I see in the shell that webpack bundles everything with no errors but if I go to localhost:3000/ it does not find any of the assets created by Webpack. Instead if I run webpack to create the various bundles as if I were on production, everything is created correctly and it works as expected.
Hope someone can figure out what I am doing wrong.
Thanks
I managed to figure out what was causing the problem, by adding a slash in these 2 lines everything started to work properly:
context: path.resolve('public/javascripts/'),
path: path.resolve('public/javascripts/build/'),

Resources