Parcel works with typescript/react-router-dom in Dev but doesn't follow router paths in Prod
See original GitHub issue🐛 bug report
Hopefully this is just a setup issue, but I don’t know where to start. I looked at a lot of other issues but didn’t see anything relevant.
In short, with Dev environment:
- Works - http://localhost:3000 (main app page)
- Works - http://localhost:3000/utilities (router linked page)
With env=Production,
- Works - http://localhost:3000 (main app page)
- broken - http://localhost:3000/utilities (router linked page)
🎛 Configuration (.babelrc, package.json, cli command)
My current repo can be see here: https://github.com/tagyoureit/nodejs-poolController/tree/6.0-DEV
// .babelrc
{
"plugins" : ["@babel/plugin-proposal-class-properties"]
}
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
// "paths": { "*": [ "@types/*" ] },
"target":"es6",
"module":"commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outDir": "dist",
"sourceMap": true,
"moduleResolution": "node",
"allowJs": true,
"allowSyntheticDefaultImports": false,
"esModuleInterop": true,
"jsx": "react"
},
"include": [
"src/**/*",
"@types"
],
"exclude": [
"dist/**/*"
]
}
// package.json
{
"name": "nodejs-poolcontroller",
"version": "6.0.0",
"description": "NodeJS program to read and write to the the pool equipment serial bus.",
"main": "src/index.js",
"scripts": {
"start": "npm run build && NODE_ENV=production node dist/index.js",
"dev": "TS_NODE_FILES=true node -r ts-node/register src/index.ts",
"build": "tsc && parcel build www/pages/index.html -d dist/www",
"start:capture": "node dist/index.js $* --capturePackets",
"start:replay": "npm run build && NODE_ENV=production node dist/index.js $* --suppressWrite",
"test": "snyk test && npm run build && NODE_ENV=production TS_NODE_FILES=true mocha --recursive './specs/**/*.spec.ts' -r ts-node/register --trace-warnings",
"test:one": "npm run build && NODE_ENV=production TS_NODE_FILES=true mocha -r ts-node/register",
"test:one:cover": "npm run build && NODE_ENV=production nyc mocha -- ./specs/assets/config/config.json ./specs/index.spec.js --include-all-sources ./specs --require ./specs/helpers/chai.js --exit",
"test:cover": "npm run build && NODE_ENV=production TS_NODE_FILES=true nyc mocha --recursive './specs/**/*.spec.ts' -r ts-node/register --trace-warnings",
"test:replay": "mocha ./specs/assets/config/config.json --require ./specs/helpers/chai.js ./specs/index.spec.js ./misc/replay.js --exit --delay",
"start:cover": "npm run build && NODE_ENV=production nyc --handle-sigint src/index.js",
"open:cover": "open coverage/lcov-report/index.html",
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"snyk-protect": "snyk protect",
"prepublishOnly": "npm run snyk-protect",
"configTester": "node misc/configTester.js"
},
"repository": {
"url": "git+https://github.com/tagyoureit/nodejs-poolController.git"
},
"keywords": [
"Pentair",
"Hayward",
"pool",
"home automation",
"solar",
"heat",
"temperature",
"pump",
"chlorinator",
"IoT"
],
"author": "Russell Goldin",
"license": "AGPL-3.0",
"bugs": {
"url": "https://github.com/tagyoureit/nodejs-poolController/issues"
},
"homepage": "https://github.com/tagyoureit/nodejs-poolController#readme",
"dependencies": {
"bluebird": "^3.5.4",
"bootstrap": "^3.4.1",
"dateformat": "^3.0.3",
"deep-diff": "^1.0.1",
"dequeue": "^1.0.5",
"express": "^4.16.4",
"getmac": "^1.4.3",
"helmet": "^3.18.0",
"http-auth": "^3.2.3",
"http-shutdown": "^1.2.0",
"influx": "^5.0.7",
"ip": "^1.1.5",
"jquery": "^3.4.1",
"jquery-ui-dist": "^1.12.1",
"logform": "^2.1.2",
"multicast-dns": "^7.0.0",
"mysql": "^2.17.1",
"node-ip": "^0.1.2",
"node-ssdp": "^4.0.0",
"parcel-bundler": "^1.12.3",
"popper.js": "^1.15.0",
"react": "^16.8.6",
"react-data-grid": "^6.1.0",
"react-dom": "^16.8.6",
"react-infinite-calendar": "^2.3.1",
"react-popper": "^1.3.3",
"react-rangeslider": "^2.2.0",
"react-router-dom": "^5.0.0",
"react-timekeeper": "^1.1.0",
"reactstrap": "^8.0.0",
"request": "^2.87.0",
"request-promise": "^4.2.4",
"serialport": "^7.1.5",
"socket.io": "^2.2.0",
"socket.io-client": "^2.2.0",
"source-map-support": "^0.5.12",
"underscore": "^1.9.1",
"validator": "^10.11.0",
"winston": "^3.2.1",
"yargs-parser": "^13.1.0"
},
"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@types/bluebird": "^3.5.26",
"@types/chai": "^4.1.7",
"@types/dateformat": "^3.0.0",
"@types/deep-diff": "^1.0.0",
"@types/express": "^4.16.1",
"@types/helmet": "0.0.43",
"@types/ip": "^1.1.0",
"@types/mocha": "^5.2.6",
"@types/nock": "^10.0.3",
"@types/node": "^11.13.10",
"@types/node-ssdp": "^3.3.0",
"@types/parcel-bundler": "^1.12.0",
"@types/react": "^16.8.17",
"@types/react-data-grid": "^4.0.2",
"@types/react-dom": "^16.8.4",
"@types/react-infinite-calendar": "^2.3.2",
"@types/react-rangeslider": "^2.2.0",
"@types/react-router-dom": "^4.3.3",
"@types/reactstrap": "^8.0.1",
"@types/request-promise": "^4.1.43",
"@types/serialport": "^7.0.3",
"@types/sinon": "^7.0.11",
"@types/socket.io": "^2.1.2",
"@types/socket.io-client": "^1.4.32",
"@types/triple-beam": "^1.3.0",
"@types/underscore": "^1.8.17",
"@types/validator": "^10.11.0",
"chai": "^4.2.0",
"coveralls": "^3.0.3",
"mocha": "^6.1.4",
"nock": "^10.0.6",
"nyc": "^14.1.1",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"snyk": "^1.164.0",
"ts-lint": "^4.5.1",
"ts-mockito": "^2.3.1",
"ts-node": "^8.1.0",
"ts-sinon": "^1.0.17",
"typescript": "^3.4.5"
},
"snyk": true,
"nyc": {
"check-coverage": false,
"per-file": true,
"include": [
"src/**/*.js",
"specs/**/*.js"
],
"exclude": [
"node_modules/**",
"www/**"
],
"reporter": [
"lcov",
"text-summary",
"html"
],
"cache": false,
"all": true,
"sourceMap": true,
"instrument": true
}
}
My main app page (app.tsx) looks like this:
import * as React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import NodeJSPoolController from '../components/PoolController'
import PacketSnifferController from '../components/utilities/PacketSnifferController'
import PacketTester from '../components/utilities/PacketTester'
import UtilitiesLayout from '../components/utilities/UtilitiesLayout'
import Replay from '../components/utilities/Replay'
const App = () => {
return (
<NodeJSPoolController />
)
}
const Utilities = () =>
{
return (
<UtilitiesLayout />
)
}
const packetSniffer = () =>
{
return (
<PacketSnifferController />
)
}
const packetTester = () =>
{
return (
<PacketTester />
)
}
const replay = () =>
{
return (
<Replay />
)
}
ReactDOM.render(
<Router>
<Route exact path="/" component={App}/>
<Route path="/packetSniffer" component={packetSniffer} />
<Route path="/utilities" component={Utilities} />
<Route path='/packetTester' component={packetTester} />
<Route path='/replay' component={replay} />
</Router>,
document.getElementById('root')
);
Where my Express server is setup, I use Parcel with Dev environment like this:
if ( dev )
{
// Parcel: absolute path to entry point
const file = path.join( process.cwd(), '/www/pages/index.html' )
logger.debug( `Parcel serving files from: ${ file }` )
// Parcel: set options
const options = {};
// Parcel: Initialize a new bundler
servers[ type ].parcel = new Bundler( file, options )
}
else
{
servers[ type ].parcel = {}
}
// ... and later
if ( dev )
{
// Parcel: middleware
app.use( bundlerParcel.middleware() )
}
For the CLI, (see package.json above)
dev: npm run dev
production: npm start
🤔 Expected Behavior
I would expect to be able to browse to http://localhost:3000/utilities
in Production just like with Dev.
😯 Current Behavior
When I browse to http://localhost:3000
everything works. However, when I try to go to http://localhost:3000/utilities
the browser gives me the message Cannot GET /utilities
.
💁 Possible Solution
Not sure where to look! Please help. 😃
🔦 Context
Trying to allow users to use the app with all the benefits of production (less memory, faster, no need for HRM, etc).
💻 Code Sample
Current repo: https://github.com/tagyoureit/nodejs-poolController/tree/6.0-DEV
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 1.12.3 |
Node | 8.16.0 |
npm/Yarn | npm 6.4.1 |
Operating System | Mac Mojave 10.14.5 |
Typescript : 3.4.5 |
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (3 by maintainers)
🎉
I’ll add it to the docs somewhere: https://github.com/parcel-bundler/website/issues/453
For Single Page (React) Apps (means client side routing), the server needs to be configured to serve the index file for any requests that aren’t found. So you need to do this: