0

I have am attempting to compile my Javascript (es6) for use server side, the environment I'm targeting involves:

node    8.9.1  
npm     6.0.0  
webpack 4.8.1

The first part of the code I'm attempting to compile using webpack is the file index.js and it starts like this.

import express from 'express';
import https from 'https';

// Import socket.io
let io = require('socket.io').Server;

// Now import some basic middleware for express
import * as session from 'express-session';
import * as bodyParser from 'body-parser';
import * as favicon from 'serve-favicon';

// Import useful file IO
import * as path from 'path';
let fs = require('fs');
...

However when I run webpack I get the following error:

$ webpack

Webpack is watching the files…

Hash: 1bd3f903f9c5ccdc3456
Version: webpack 4.8.1
Time: 684ms
Built at: 2018-05-10 14:51:08
                       Asset      Size  Chunks             Chunk Names
                   server.js  3.97 KiB    main  [emitted]  main
               server.js.map  2.52 KiB    main  [emitted]  main
../dist/keys/it-test-crt.crt  1.16 KiB          [emitted]  
  ../dist/images/favicon.ico  1.19 KiB          [emitted]  
../dist/keys/it-test-csr.pem  1.02 KiB          [emitted]  
../dist/keys/it-test-key.pem  1.64 KiB          [emitted]  
Entrypoint main = server.js server.js.map
[./index.js] 1.2 KiB {main} [built] [failed] [1 error]

ERROR in ./index.js
    Module build failed: Error: Parse Error: Line 1: Illegal import declaration
...

BTW I am using Javascript in it's es6 incarnation so do need Bable and it is in my configs (q.v.). Even if I was not using es6 the Webpack documentation suggests that import should be respected regardless, see here, where the Webpack documentations says:

Version 2 of webpack supports ES6 module syntax natively, meaning you can use import and export without a tool like babel to handle this for you.

So my question is why do I see the above error? My current assumption is I have made an error somewhere in my configuration of Webpack, see below:

var nodeExternals = require('webpack-node-externals');
var CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    context:        __dirname,

    mode:           'development',

    entry:          './index.js',

    output:         {
                    filename:   'server.js',
                    path:        __dirname + '/../dist/'
                    },

    devtool:        'source-map',

    resolve:        {
                    extensions: ['.js', '.jsx', '.json'],
                    modules: ['./', 'node_modules']
                    },

    module:         {
                    rules:[
                            {
                            test: /\.js?$/,
                            use: {
                                loader: 'babel-loader?presets[]=env',
                                }
                            },
                            {
                            test: /\.jsx?$/,
                            use: {
                                loader: 'jsx-loader?harmony'
                            }
                            },
                            {
                            enforce: 'pre',
                            test: /\.js$/,
                            loader: 'source-map-loader'
                            }
                        ]
                    },

    target:         'node',

    node:           {
                    __dirname: false,
                    __filename: false
                    },

    externals:      [nodeExternals()],

    watch:          true,

    watchOptions:   {
                    ignored: /node_modules/
                    },

    plugins:        [
                    new CopyWebpackPlugin([
                        {from:  'images',   to: '../dist/images'},
                        {from:  'keys',     to: '../dist/keys'}
                        ])
                    ]
  };

I have not set up a .babelrc file as I was appending the presets[]=env query to the babel-loader. Just in case it's helpful to know any other version numbers my package.json looks like this:

{
"name": "web-app",
"version": "1.0.0",
"description": "A web application using react, etc. ",
"main": "index.js",
"repository": {
    "type": "git",
    "url": "git+https://github.com/nigel-daniels/web-app.git"
    },
"keywords": [
    "web",
    "app",
    "react",
    "redux"
    ],
"author": "Nigel Daniels",
"license": "MIT",
"bugs": {
    "url": "https://github.com/nigel-daniels/web-app/issues"
    },
"homepage": "https://github.com/nigel-daniels/web-app#readme",
"dependencies": {
    "async": "^2.6.0",
    "bcrypt-nodejs": "0.0.3",
    "body-parser": "^1.18.2",
    "cookie-parser": "^1.4.3",
    "debug": "^3.1.0",
    "express": "^4.16.2",
    "express-session": "^1.15.6",
    "express-socket.io-session": "^1.3.2",
    "fs": "0.0.1-security",
    "immutable": "^3.8.2",
    "mongoose": "^5.0.6",
    "nodemailer": "^4.4.0",
    "passport": "^0.4.0",
    "passport-local": "^1.0.0",
    "react": "^16.1.1",
    "react-dom": "^16.1.1",
    "redux": "^3.7.2",
    "serve-favicon": "^2.4.5",
    "socket.io": "^2.0.4"
    },
"devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "chai": "^3.5.0",
    "chai-immutable": "^1.6.0",
    "copy-webpack-plugin": "^4.2.3",
    "jsx-loader": "^0.13.2",
    "mocha": "^5.0.1",
    "source-map-loader": "^0.2.3",
    "webpack": "^4.8.1",
    "webpack-node-externals": "^1.7.2"
    },
"engines": {
    "node": "^8.1.0",
    "npm": "6.0.0"
    }
}

Thanks for any advice!

JSDevGuy
  • 127
  • 2
  • 11

2 Answers2

0

I think the problem is that it the express module exports with module.exports, while you import with es2015 import. I don't think webpack supports the conversion natively. I would just use require instead when importing npm modules, but otherwise you this babel plugin might solve it for you: https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs.

Mattias
  • 715
  • 1
  • 6
  • 19
0

You shouldn't need jsx-loader for a nodejs backend build. You can remove it and if necessary, let babel-loader handle .jsx extensions for you:

{
  test: /\.jsx?$/, // notice the little 'x'
  use: {
      loader: 'babel-loader?presets[]=env',
    }
 },
MadeOfAir
  • 2,933
  • 5
  • 31
  • 39
  • Thanks @MadeOfAir that's got me on the correct path. For me the full solution was to add the little x, but I did need a full jsx builder as I have some server-side jsx. The full solution was to do the following: – JSDevGuy May 11 '18 at 22:23
  • 1) install the bable jsx preset: `npm install --save-dev babel-preset-react` 2) Add a `.babelrc` file containing: `{ "presets": ["env", "react"] }` 3) add the little x and remove the query so the module rule becomes: `{ test: /\.jsx?$/, // notice the little 'x'. use: { loader: 'babel-loader', // no query } },` – JSDevGuy May 11 '18 at 22:29