10

I'm trying to update my app node backend to typescript and I keep hitting this syntax error:

/Users/Shared/website/src/server.ts:1
(function (exports, require, module, __filename, __dirname) { import * 
as express from 'express';
                                                                 ^

SyntaxError: Unexpected token *

I have my tsconfig/webpack/server, etc set up as follows:

server.ts

import * as express from 'express';
import * as path from 'path';

const app = express();
const port = process.env.PORT || 3000;

app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', function(req, res, next){
    res.sendFile(path.resolve(__dirname, '/public', 'index.html'));
});

app.listen(port, () => console.log(`Listening on port ${port}!`));

webpack.config.json:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const outputDirectory = 'dist';

module.exports = {
    entry: "./src/index.tsx",
    output: {
        filename: "bundle.js",
        path: path.join(__dirname, outputDirectory)
    },
    mode: 'development',

    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".ts", ".tsx", ".js", ".json"]
    },

    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.tsx?$/, loader: "ts-loader" },

            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

            {
                test: /\.scss$/,
                use: [
                    "style-loader", // creates style nodes from JS strings
                    "css-loader", // translates CSS into CommonJS
                    "sass-loader" // compiles Sass to CSS, using Node Sass by default
                ]
            }
        ]
    },

    // When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    externals: {
    },

    plugins: [
        new CleanWebpackPlugin([outputDirectory]),
        new HtmlWebpackPlugin({
          template: './public/index.html',
          favicon: './public/favicon.gif'
        }),
        new CopyWebpackPlugin([
            { from: 'public' }
        ])
    ]
};

tsconfig.json:

{
    "compilerOptions": {
        "outDir": "./dist/",
        "sourceMap": true,
        "noImplicitAny": false,
        "module": "commonjs",
        "target": "es6",
        "jsx": "react"
    },
    "include": [
        "./src/**/*"
    ],
}

The build process succeeds, but I hit the syntaxError on run. I have a react front end also set up using typescript / tsx and it works just fine. I seem to just be running into issues with the server.ts / node files. I'm very new to trying to get this all set up, but I wanted practice making a site with numerous technologies (react/node/typescript/sass/webpack/etc). So far I have everything except the typescript/node relationship.

jajabarr
  • 247
  • 3
  • 15
  • 2
    For some reason tsconfig you've posted isn't applied. If `"module": "commonjs"` was in effect, you wouldn't have this error. – Estus Flask Sep 22 '18 at 21:01
  • What might cause it not being applied? How could I mitigate that? – jajabarr Sep 22 '18 at 22:08
  • There could be another tsconfig that overrides this one, or anything else. The problem is specific to your setup. Please, provide a way to replicate the problem - a repo, etc. See https://stackoverflow.com/help/mcve – Estus Flask Sep 22 '18 at 22:15

5 Answers5

6

I had the same problem, after I realised that the tsconfig wasn't applied.

If

"module": "commonjs" 

was in effect, you wouldn't have this error.

freedev
  • 17,230
  • 4
  • 83
  • 98
5

I faced the same problem before. I solve it by changing the import 'call':

From:

import * as express from 'express';

To:

const express = require('express');
Rodrigo Aires
  • 199
  • 1
  • 6
  • 2
    To clarify on why this works, Node does not actually support ES6 Modules yet. Check out these links that I was able to dig up: [Experimental support](https://nodejs.org/api/esm.html), [a related SO question](https://stackoverflow.com/questions/45854169/how-can-i-use-an-es6-import-in-node), and [a GitHub issue](https://github.com/nodejs/modules/issues/253) – Bpainter Feb 08 '19 at 22:40
1

As others have stated, the problem is that your tsconfig.json is not applied to server.ts. You have left out important details of your setup which is why others cannot duplicate this problem.

I have a good guess at what the issue is and having struggled with this identical problem myself, I will explain my guess here in the hope of helping some other poor soul being tormented by this issue.

The basic problem is that your server code is in a different tree than your react code. This is why the tsconfig.json is not being applied to it since (I believe) it is outside the "./src/" path specified. (Perhaps "./website/src/").

You haven't shown us the package.json file but very likely the server entry is something like "server": "ts-node ./website/src/server.ts"

To verify that the tsconfig.json application is the issue try this from the command line...

$ ts-node -O '{\"module\":\"commonjs\"}' ./website/src/server.ts

Chances are, things will start working. Now the solution is probably as simple as adding another path your tsconfig.json includes.

AQuirky
  • 3,448
  • 1
  • 19
  • 41
0

So I came across this post on github where basically there are two sort of working methods presented since you’re using a bundling tool targeted to es6 add

"allowSyntheticDefaultImports": true to ”compilerOptions”

Or change

import express from "express";

to

import express = require('express');
Vaibhav Kumar Goyal
  • 1,391
  • 12
  • 17
  • 1
    That link doesn't appear to be entirely relevant to the problem I'm having. OP in that post is able to compile 'import * as express from 'express'; I am not able to use npm run start on a file with this syntax, which is the problem I am having. Neither of the suggested solutions worked for me. When I try 'import express from 'express'; I hit "Unexpected token 'express'" – jajabarr Sep 22 '18 at 20:36
0

This might be happening if your tsconfig.json isn't at the root of your project. Configure webpack to point to your target config file (which you can alter with variables to point to dev and prod configurations).

https://github.com/TypeStrong/ts-loader

If set, will parse the TypeScript configuration file with given absolute path as base path. Per default the directory of the configuration file is used as base path. Relative paths in the configuration file are resolved with respect to the base path when parsed. Option context allows to set option configFile to a path other than the project root (e.g. a NPM package), while the base path for ts-loader can remain the project root.

Try modifying your webpack.config.js file to have this:

module.exports = {
  ...
  module: {
    rules: [
      {
        options: {
          configFile: path.join(__dirname, "tsconfig.json")
        }
      }
    ]
  }
};
nwayve
  • 1,995
  • 20
  • 30