Reputation: 110
I followed the instructions to create a webpack build environment from the angular.io site: https://angular.io/docs/ts/latest/guide/webpack.html, and got it working. Then, I took the Tour of Heroes tutorial that I got working, and I migrated it to a webpack environment.
If I run the Tour of Heroes using the webpack dev environment (with npm start
), it works great. If I then create a production build (with npm run build
), and serve the resulting files with node, I cannot get the server to respond when I try to access a URL directly. Below I will outline the steps to create the environment and the problem step-by-step. I believe the solution is to modify my server.js file, but I don't know what is needed.
How to recreate:
app
folder from the Tour of Heroes liteserver environment to the src
folder of the webpack environmentIn index.html of the webpack environment, comment out (or remove) all the scripts for polyfills and Configure SystemJS. Index.html should look like this:
<html>
<head>
<base href="/">
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--
<link rel="stylesheet" href="styles.css">
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
-->
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
Modify the package.json so it has what is needed from both environments. Mine looks like this:
{
"name": "angular2-webpack",
"version": "1.0.0",
"description": "A webpack starter for Angular",
"scripts": {
"start": "webpack-dev-server --inline --progress --port 8080",
"test": "karma start",
"build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/angular/angular.io/blob/master/LICENSE"
}
],
"dependencies": {
"@angular/common": "~2.1.1",
"@angular/compiler": "~2.1.1",
"@angular/core": "~2.1.1",
"@angular/forms": "~2.1.1",
"@angular/http": "~2.1.1",
"@angular/platform-browser": "~2.1.1",
"@angular/platform-browser-dynamic": "~2.1.1",
"@angular/router": "~3.1.1",
"angular2-cool-storage": "^1.1.0",
"angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.25"
},
"devDependencies": {
"@types/core-js": "^0.9.34",
"@types/node": "^6.0.45",
"@types/jasmine": "^2.5.35",
"angular2-template-loader": "^0.4.0",
"awesome-typescript-loader": "^2.2.4",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.15.0",
"jasmine-core": "^2.4.1",
"karma": "^1.2.0",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0",
"null-loader": "^0.1.1",
"phantomjs-prebuilt": "^2.1.7",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"style-loader": "^0.13.1",
"typescript": "^2.0.3",
"webpack": "^1.13.0",
"webpack-dev-server": "^1.14.1",
"webpack-merge": "^0.14.0"
}
}
From the webpack folder, run npm install
npm run build
to create prod build files. This is what the webpack tutorial says to do.Create a server.js file at the root that looks like this:
var express = require("express");
var app = express();
app.use(function(req, res, next) {
console.log("Request recieved for:", req.url);
next();
});
app.use(express.static('public'));
app.use(function(req, res, next) {
res.status(404);
res.send('404 file not found');
});
app.listen(4040, function() {
console.log("yes: 4040");
});
In the node environment, create a public
folder, and put all the files from the dist
folder that was created in step 6 into the public folder.
node server.js
http://localhost:4040/heroes
npm start
, you can go to the URL directly http://localhost:4040/heroes
and it works fine.If you want to see all the code for this, here is the github repo: https://github.com/joshuaforman/heroeswebpack
Upvotes: 2
Views: 1079
Reputation: 110
I've got it figured out. The issue was in the server.js. After more research, I found this: https://expressjs.com/en/starter/static-files.html. Need to add more middleware after the express.static middleware: app.use('/heroes', express.static('public'));
. The direct URLs work as needed with this server.js file:
var express = require("express");
var app = express();
app.use(function(req, res, next) {
console.log("Request recieved for:", req.url);
next();
});
app.use(express.static('public'));
app.use('/heroes', express.static('public'));
app.use('/dashboard', express.static('public'));
app.use(function(req, res, next) {
res.status(404);
res.send('404 file not found');
});
app.listen(4040, function() {
console.log("yes: 4040");
});
The app I'm working on also needs to pass params, so if you need to do that, you will need middleware of this format:
app.get('/peopledetails/:uid', function(req, res){
var uid = req.params.uid,
path = req.params[0] ? req.params[0] : 'index.html';
res.sendFile(path, {root: './public'});
});
Thanks to this stack question for the above: Serve Static Files on a Dynamic Route using Express.
Thanks for the help, folks.
Upvotes: 3