question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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:

With env=Production,

🎛 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:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mischniccommented, Jun 3, 2019

🎉

Just out of curiosity, is this documented somewhere that I should have been able to find it? Seems like such a basic setup that I should have come across it in my Googling.

I’ll add it to the docs somewhere: https://github.com/parcel-bundler/website/issues/453

1reaction
mischniccommented, Jun 3, 2019

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:

import * as http from "http";
import express = require("express");
const path = require("path").posix;
import Bundler = require("parcel-bundler");

let app: express.Application = express();

if (process.env.NODE_ENV !== "production") {
    const entry = path.join(process.cwd(), "/www/index.html");
    let parcel = new Bundler(entry, {
        outDir: "./dist/dev"
    });
    app.use(parcel.middleware());
} else {
    app.use(
        express.static(path.join(process.cwd(), "/dist/www"), { maxAge: "14d" })
    );

    // Single Page App: fallback to index.html
    app.get("*", (req, res) =>
        res.sendFile(path.join(__dirname + "/www/index.html"))
    );
}

http.createServer(app).listen(3000, () => {
    console.log(`http server started on port 3000`);
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

Can't resolve 'react-router-dom' - Stack Overflow
I was facing the same issue. The following command will resolve it: npm install react-router-dom --save.
Read more >
How to Use React Router in Typescript | Pluralsight
On line 31 we define a Product route that responds to any URL that starts with "/product/" and has product's ID in its...
Read more >
Fixing the 'cannot GET /URL' error on refresh with React ...
There are two main ideas for solving this problem. The first, set up both client and server side routing. The second, redirect all...
Read more >
Getting started with React - Learn web development | MDN
React uses an HTML-in-JavaScript syntax called JSX (JavaScript and XML). Familiarity with both HTML and JavaScript will help you to learn JSX, ...
Read more >
Module not found: Can't resolve 'react-router-dom' | bobbyhadz
If you're still getting the "Module not found: Error: Can't resolve 'react-router-dom'" error, open your package.json file and make sure it contains the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found