Getting Started with Isomorphic React at Pluralsight

Isomorphic React, for many reasons, is gaining traction with many developers. Not least for the SEO benefits – or should we say that massive SEO pitfalls of *NOT* using isomorphic React. Blank pages for Googlebot anyone?

Anyway, a great course available for this very topic, that covers Isomorphic React in a concise fashion is Dan Sterns course over at Pluralsight.

I myself have also started looking at this course – and for anyone else who has started recently, they may have hit a snag with the demo.

Dan provides a starting template for the course – only issue is, that the template falls over with an error after you’ve followed the initial instructions to npm install, npm post install and npm start in the second module ‘Course Introduction’.

A few people have been discussing this on the Isomorphic React course discussion page and a few people have tried to help, but it appears Dan hasn’t had a chance to provide an update yet – probably because he’s uber busy with a load of other things at the moment as many of us are!

Unfortunately, there’s a couple of pieces of the answer missing to get up and running and some helpful steps along the way that are spread out so I’m writing this article to put the solution in one place. Don’t worry, I will of course also be submitting a pull request to Daniel to help get this fixed in the git repo also.

The Issue with the Isomorphic React Template

So, you followed all the instructions, you’re raring to go and boom!

So what does this mean? Short answer, the app isn’t running.

Slightly longer answer (just about!): Uglify can’t understand the pretty new ES6 syntax that we’re all using (or should be using!) by now.

Full error stack included below:

PS C:\Pluralsight\Isomorphic-React\> npm start

> isomorphic-react@1.0.0 start C:\Pluralsight\Isomorphic-React\isomorphic-react
> npm run start-prod


> isomorphic-react@1.0.0 start-prod C:\Pluralsight\Isomorphic-React\
> npm run build && cross-env NODE_ENV=production babel-node server --useServerRender=true --useLiveData=false


> isomorphic-react@1.0.0 build C:\Pluralsight\Isomorphic-React\
> cross-env webpack --config ./webpack.config.prod.babel.js

C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:178
    throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
    ^

Error: Plugin/Preset files are not allowed to export objects, only functions. In C:\Pluralsight\Isomorphic-React\node_modules\babel-preset-es2015\lib\index.js      
    at createDescriptor (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:178:11)
    at C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:109:50
    at Array.map (<anonymous>)
    at createDescriptors (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:109:29)
    at createPresetDescriptors (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:101:10)
    at presets (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-descriptors.js:47:19)
    at mergeChainOpts (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-chain.js:320:26)
    at C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-chain.js:283:7
    at buildRootChain (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\config-chain.js:120:22)
    at loadPrivatePartialConfig (C:\Pluralsight\Isomorphic-React\node_modules\@babel\core\lib\config\partial.js:85:55)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 build: `cross-env webpack --config ./webpack.config.prod.babel.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_35_22_069Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start-prod: `npm run build && cross-env NODE_ENV=production babel-node server --useServerRender=true --useLiveData=false`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 start-prod script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_35_22_139Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start: `npm run start-prod`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_35_22_237Z-debug.log

Fixing Isomorphic React Template

The two main areas that need updating are the depdencies and the webpack configuration. I’ll detail the specific steps below.

There’s obviously more than one way to skin a cat – or, in this case, fix a programming template, but we’ve tried and tested this way and all seems fine up to now (we’ll provide updates here if we discover any issues or come up with a more optimum fix).

The main steps are to teach Uglify ES6 (via the very handy uglifyjs-webpack-plugin), upgrade webpack – including adding the recommended webpack command line interface and then substituting the webpack config and including some nice new config features that are part of Webpack 4.

Step 1 – Upgrade Webpack

We’re going to take advantage of some new features of Webpack (such as the optimisation configuration) and this requires an upgrade to Webpack 4.x

You can:

Run:

npm update webpack

Or Change the package.json file directly and run:

npm install

Or you can run:

npm uninstall webpack
npm install webpack

To install the latest version (currently 4.42.1).

Step 2 – Add The Webpack CLI

This isn’t included in the original template – but is a recommended part of Webpack 4.x so we ought to add it.

You can do this by running the following command in Powershell:

npm install webpack-cli

If you get giddy and forget this step, you will get a reminder when we start later that the command line interface is missing and you ought to add it:

One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:
 - webpack-cli (https://github.com/webpack/webpack-cli)
   The original webpack full-featured CLI.
We will use "npm" to install the CLI via "npm install -D".
Do you want to install 'webpack-cli' (yes/no):

Enter ‘yes’ here at the prompt and the default webpack-cli will be installed:

Installing 'webpack-cli' (running 'npm install -D webpack-cli')...
npm WARN webpack-dev-middleware@1.12.2 requires a peer of webpack@^1.0.0 || ^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN isomorphic-react@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ webpack-cli@3.3.11
added 38 packages from 24 contributors and audited 870908 packages in 22.005s

1 package is looking for funding
  run `npm fund` for details

Step 3 – Install UglifyJS Webpack Plugin

Remember when we said we have to teach Uglify JS ES6? Don’t worry, it’s not like homeschooling! The UglifyJS Webpack Plugin will do the heavy lifting for us!

This isn’t part of the template project so we just need to npm install the latest version:

npm install uglifyjs-webpack-plugin

That’ll whirl away as usual and install in the background.

Step 4 – Updating the Webpack Config

Now onto the final step – updating the webpack config.

One of the key differences is what we’ll need to include our new UglifyJS Webpack plugin that we installed in the previous step:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

This should be included at the top along with the path and webpack dependencies.

Then we add a mode:

  • development‘: for webpack.config.dev.babel.js
  • production‘: for webpack.config.prod.babel.js

The next major change is the addition of a brand new optimisation (or optimization in American English) object which includes a minimiser (minimizer) array that calls our newly included UglifyJS plugin to, among other things, parse ES6 and sort out the source maps.

There are some other minor changes and renames for Webpack 4 compatibility but we won’t cover them explicitly in detail at the moment.

New Dev Webpack Configuration

Below is the complete development Webpack configuration with all the updates required included. Feel free to drop this straight into your webpack.config.dev.babel.js file:

const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const webpack = require('webpack');

module.exports = {
    mode: 'development',
    entry: [
        'babel-regenerator-runtime',
        path.resolve(__dirname, 'src')
    ],
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    optimization: {
        minimizer: [
            // we specify a custom UglifyJsPlugin here to get source maps in production
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                uglifyOptions: {
                    compress: false,
                    ecma: 6,
                    mangle: true
                },
                sourceMap: true
            })
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production'),
                WEBPACK: true
            }
        }),
        /*
        * Uglifies JS which improves performance
        * React will throw console warnings if this is not implemented
        */
    ],
    resolve: {
        extensions: ['.js', '.json', '.jsx'],
    },
    module: {
        rules: [
            {
                test: /.jsx?$/,
                use: {
                    loader: 'babel-loader'
                },
                include: path.resolve(__dirname, 'src')
            }
        ]
    }
};

New Production Webpack Config

For the webpack.config.prod.babel.js, the main change is to update the mode to ‘production’ to take advantage of additional optimisations available for a build environment:

mode: 'production'

The New Webpack Config Doesn’t Work!

It does, trust me! The error you’re probably encountering is that you’ve skipped updating the webpack depedency – this is by far the most common. As the new configuration takes advantage of some new features of Webpack 4 – such as optimisation – Webpack 3.x will throw a hissy fit if you don’t upgrade:

Invalid configuration object - optimisation - Webpack 3.x

The full error stack is included below for convienience:

PS C:\Pluralsight\Isomorphic-React> npm start

> isomorphic-react@1.0.0 start C:\Pluralsight\Isomorphic-React
> npm run start-prod


> isomorphic-react@1.0.0 start-prod C:\Pluralsight\Isomorphic-React
> npm run build && cross-env NODE_ENV=production babel-node server --useServerRender=true --useLiveData=false


> isomorphic-react@1.0.0 build C:\Pluralsight\Isomorphic-React
> cross-env webpack --config ./webpack.config.prod.babel.js

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration has an unknown property 'optimization'. These properties are valid:
   object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry, externals?, loader?, module?, name?, node?, output?, parallelism?, performance?, plugins?, profile?, 
recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }
   For typos: please correct them.
   For loader options: webpack 2 no longer allows custom properties in configuration.
     Loaders should be updated to allow passing options via loader options in module.rules.
     Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:
     plugins: [
       new webpack.LoaderOptionsPlugin({
         // test: /\.xxx$/, // may apply this only for some modules
         options: {
           optimization: ...
         }
       })
     ]
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 build: `cross-env webpack --config ./webpack.config.prod.babel.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_49_53_357Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start-prod: `npm run build && cross-env NODE_ENV=production babel-node server --useServerRender=true --useLiveData=false`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 start-prod script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_49_53_424Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start: `npm run start-prod`
npm ERR! Exit status 1
npm ERR!
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T15_49_53_507Z-debug.log
PS C:\Pluralsight\Isomorphic-React> rm -rf node_modules
At line:1 char:4
+ rm -rf node_modules
+    ~~~
    + CategoryInfo          : InvalidArgument: (:) [Remove-Item], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

Go back to Step 1 above, upgrade webpack and you should be sorted!

Error: Cannot find module!

Sounds like you’ve skipped step 3 – installing the uglify-js-webpack-plugin. Go back and do this and you should be good to go. The good news is, step 4 – replacing webpack config went well if you’re getting this error message!

Full error stack for this one is listed below:

Error: Cannot find module 'uglifyjs-webpack-plugin'
Require stack:
- C:\Pluralsight\Isomorphic-React\webpack.config.prod.babel.js
- C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\utils\convert-argv.js
- C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\cli.js
- C:\Pluralsight\Isomorphic-React\node_modules\webpack\bin\webpack.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:797:15)
    at Function.Module._load (internal/modules/cjs/loader.js:690:27)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (C:\Pluralsight\Isomorphic-React\node_modules\v8-compile-cache\v8-compile-cache.js:161:20)
    at Object.require (C:\Pluralsight\Isomorphic-React/webpack.config.prod.babel.js:2:24)
    at Module._compile (C:\Pluralsight\Isomorphic-React\node_modules\v8-compile-cache\v8-compile-cache.js:192:30)
    at Module._compile (C:\Pluralsight\Isomorphic-React\node_modules\pirates\lib\index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Object.newLoader [as .js] (C:\Pluralsight\Isomorphic-React\node_modules\pirates\lib\index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (C:\Pluralsight\Isomorphic-React\node_modules\v8-compile-cache\v8-compile-cache.js:161:20)
    at WEBPACK_OPTIONS (C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\utils\convert-argv.js:114:13)
    at requireConfig (C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\utils\convert-argv.js:116:6)
    at C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\utils\convert-argv.js:123:17
    at Array.forEach (<anonymous>)
    at module.exports (C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\utils\convert-argv.js:121:15)
    at C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\cli.js:71:45
    at Object.parse (C:\Pluralsight\Isomorphic-React\node_modules\yargs\yargs.js:567:18)
    at C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\cli.js:49:8
    at Object.<anonymous> (C:\Pluralsight\Isomorphic-React\node_modules\webpack-cli\bin\cli.js:366:3)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at C:\Pluralsight\Isomorphic-React\node_modules\webpack\bin\webpack.js:143:5
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\Pluralsight\\Isomorphic-React\\webpack.config.prod.babel.js',
    'C:\\Pluralsight\\Isomorphic-React\\node_modules\\webpack-cli\\bin\\utils\\convert-argv.js',
    'C:\\Pluralsight\\Isomorphic-React\\node_modules\\webpack-cli\\bin\\cli.js',
    'C:\\Pluralsight\\Isomorphic-React\\node_modules\\webpack\\bin\\webpack.js'
  ]
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 build: `cross-env webpack --config ./webpack.config.prod.babel.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T16_02_09_115Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start-prod: `npm run build && cross-env NODE_ENV=production babel-node server --useServerRender=true --useLiveData=false`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the isomorphic-react@1.0.0 start-prod script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T16_02_09_312Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! isomorphic-react@1.0.0 start: `npm run start-prod`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the isomorphic-react@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\DPS Computing\AppData\Roaming\npm-cache\_logs\2020-03-31T16_02_09_395Z-debug.log

Still Got An Issue?

Let us know in the comments below and we’ll try to help solve!

What About That Pull Request?

I know, I promised didn’t I? Don’t worry, I’ll get it over to Dan ASAP.

You may also like...

4 Responses

  1. William Alex says:

    Thanks for your informative discussion.

    • DPS David says:

      Hey William, thanks for stopping by and thanks for getting involved! Great to see you around here and thanks for the feedback! Look forward to seeing you on other posts too! 🙂

  2. Angel Ana says:

    Stunning post with valuable information.

%d bloggers like this: