title: Issue with setup and run Electron + React + Typescript + Webpack application
body: <p>I'm trying to run my Electon application that I'm migrating from ES6 to Typescript. With my configuration I can build dll and main successfully but get an error (SyntaxError: Unexpected token ...) when I'm trying to run.
  For now project files are mix of typescript and javascript files.</p>
  
  <p>I use the following dependencies (main of them are):</p>
  
  <pre><code>"@babel/core": "^7.2.2", "@babel/register": "^7.0.0" and others @babel.
  "electron": "6.0.2"
  "react": "^16.9.0",
  "typescript": "^3.5.3",
  "webpack": "^4.39.2"
  </code></pre>
  
  <ol>
  <li>Scripts for run in package.json</li>
  </ol>
  
  <pre><code>"build": "concurrently \"npm run build-main\" \"npm run build-renderer\"",
  "build-dll": "cross-env NODE_ENV=development node --trace-warnings -r @babel/register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.dev.dll.js --colors",
  "build-e2e": "cross-env E2E_BUILD=true npm run build",
  "build-main": "cross-env NODE_ENV=production node --trace-warnings -r @babel/register ./node_modules/webpack/bin/webpack --config webpack.config.main.prod.js --colors",
  "build-renderer": "cross-env NODE_ENV=production node --trace-warnings -r @babel/register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.prod.js --colors",
  "electron-rebuild": "electron-rebuild --parallel --force --types prod,dev,optional --module-dir app",
  "dev": "cross-env START_HOT=1 node -r @babel/register ./scripts/CheckPortInUse.js &amp;&amp; cross-env START_HOT=1 npm run start-renderer-dev",
  "start-main-dev": "cross-env HOT=1 NODE_ENV=development electron -r @babel/register ./app/main.dev.js",
  "start-renderer-dev": "cross-env NODE_ENV=development node --trace-warnings -r @babel/register ./node_modules/webpack-dev-server/bin/webpack-dev-server --config webpack.config.renderer.dev.js",
  </code></pre>
  
  <ol start="2">
  <li>tsconfig.json</li>
  </ol>
  
  <pre><code>{
    "compilerOptions": {
      "target": "es5",
      "lib": [
        "dom",
        "dom.iterable",
        "esnext"
      ],
      "outDir": "./dist",
      "allowJs": true,
      "skipLibCheck": true,
      "esModuleInterop": true,
      "allowSyntheticDefaultImports": true,
      "strict": true,
      "strictNullChecks": false,
      "forceConsistentCasingInFileNames": true,
      "module": "esnext",
      "moduleResolution": "node",
      "resolveJsonModule": true,
      "isolatedModules": true,
      "sourceMap": true,
      "noImplicitAny": false,
      "jsx": "react",
    },
    "include": [
      "./app"
    ],
    "exclude": [
      "node_modules",
      "**/node_modules/*",
      "dist"
    ]
  }
  </code></pre>
  
  <ol start="3">
  <li>.babelrc</li>
  </ol>
  
  <pre><code>{
    "presets": [
      ["@babel/preset-env", {
        "targets": { "electron": "6.0.2" },
        "corejs": "2",
        "useBuiltIns": "usage"
      }],
      "@babel/preset-typescript",
      "@babel/preset-react"
    ],
    "plugins": [
      // Stage 0
      "@babel/plugin-proposal-function-bind",
  
      // Stage 1
      "@babel/plugin-proposal-export-default-from",
      "@babel/plugin-proposal-logical-assignment-operators",
      ["@babel/plugin-proposal-optional-chaining", {
        "loose": false
      }],
      ["@babel/plugin-proposal-pipeline-operator", {
        "proposal": "minimal"
      }],
      ["@babel/plugin-proposal-nullish-coalescing-operator", {
        "loose": false
      }],
      "@babel/plugin-proposal-do-expressions",
  
      // Stage 2
      ["@babel/plugin-proposal-decorators", {
        "legacy": true
      }],
      "@babel/plugin-proposal-function-sent",
      "@babel/plugin-proposal-export-namespace-from",
      "@babel/plugin-proposal-numeric-separator",
      "@babel/plugin-proposal-throw-expressions",
  
      // Stage 3
      "@babel/plugin-syntax-dynamic-import",
      "@babel/plugin-syntax-import-meta",
      ["@babel/plugin-proposal-class-properties", {
        "loose": true
      }],
      "@babel/plugin-proposal-json-strings",
      "@babel/plugin-proposal-object-rest-spread"
    ],
    "env": {
      "production": {
        "plugins": [
          "babel-plugin-dev-expression",
          "@babel/plugin-transform-react-constant-elements",
          "@babel/plugin-transform-react-inline-elements",
          "babel-plugin-transform-react-remove-prop-types"
        ]
      },
      "development": {
        "plugins": [
          "@babel/plugin-syntax-typescript",
          "react-hot-loader/babel"
        ]
      }
    }
  }
  </code></pre>
  
  <ol start="4">
  <li>webpack.config.base.js</li>
  </ol>
  
  <pre><code>import path from 'path';
  import webpack from 'webpack';
  import fs from 'fs';
  import { dependencies as externals } from './app/package.json';
  import { dependencies as possibleExternals } from './package.json';
  
  export default {
    externals: [
      ...Object.keys(externals || {}),
      ...Object.keys(possibleExternals ||{})
    ],
  
    module: {
      rules: [
        {
          test: /\.(js|jsx|tsx|ts)$/,
          exclude: /node_modules/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true
              }
            },
            'ts-loader'
          ]
        }
      ]
    },
  
    output: {
      path: path.join(__dirname, 'app'),
      // https://github.com/webpack/webpack/issues/1114
      libraryTarget: 'commonjs2'
    },
  
    resolve: {
      extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
      modules: [path.join(__dirname, 'app'), 'node_modules']
    },
  
    plugins: [
      new webpack.EnvironmentPlugin({
        NODE_ENV: 'production'
      }),
  
      new webpack.NamedModulesPlugin()
    ]
  };
  
  </code></pre>
  
  <ol start="5">
  <li>webpack.config.renderer.dev.dll.js</li>
  </ol>
  
  <pre><code>/**
   * Builds the DLL for development electron renderer process
   */
  import webpack from 'webpack';
  import path from 'path';
  import merge from 'webpack-merge';
  import baseConfig from './webpack.config.base';
  import { dependencies } from './package.json';
  import CheckNodeEnv from './scripts/CheckNodeEnv';
  
  CheckNodeEnv('development');
  
  const dist = path.resolve(process.cwd(), 'dll');
  
  export default merge.smart(baseConfig, {
  
    devtool: 'eval',
  
    mode: 'development',
  
    target: 'electron-renderer',
  
    externals: ['fsevents', 'crypto-browserify'],
  
    module: require('./webpack.config.renderer.dev').default.module,
  
    entry: {
      renderer: Object.keys(dependencies || {}).filter(
        dependency =&gt; dependency !== 'font-awesome'
      )
    },
  
    output: {
      library: 'renderer',
      path: dist,
      filename: '[name].dev.dll.js',
      libraryTarget: 'var'
    },
  
    plugins: [
      new webpack.DllPlugin({
        path: path.join(dist, '[name].json'),
        name: '[name]'
      }),
  
      new webpack.EnvironmentPlugin({
        NODE_ENV: 'development'
      }),
  
      new webpack.LoaderOptionsPlugin({
        debug: true,
        options: {
          context: path.resolve(process.cwd(), 'app'),
          output: {
            path: path.resolve(process.cwd(), 'dll')
          }
        }
      })
    ]
  });
  
  </code></pre>
  
  <ol start="6">
  <li>webpack.config.renderer.dev.js</li>
  </ol>
  
  <pre><code>import path from 'path';
  import fs from 'fs';
  import webpack from 'webpack';
  import chalk from 'chalk';
  import merge from 'webpack-merge';
  import { spawn, execSync } from 'child_process';
  import ExtractTextPlugin from 'extract-text-webpack-plugin';
  import baseConfig from './webpack.config.base';
  import CheckNodeEnv from './scripts/CheckNodeEnv';
  
  CheckNodeEnv('development');
  
  const port = process.env.PORT || 1212;
  const publicPath = `http://localhost:${port}/dist`;
  const dll = path.resolve(process.cwd(), 'dll');
  const manifest = path.resolve(dll, 'renderer.json');
  const requiredByDLLConfig = module.parent.filename.includes(
    'webpack.config.renderer.dev.dll'
  );
  
  if (!requiredByDLLConfig &amp;&amp; !(fs.existsSync(dll) &amp;&amp; fs.existsSync(manifest))) {
    execSync('npm run build-dll');
  }
  
  export default merge.smart(baseConfig, {
    devtool: 'inline-source-map',
  
    mode: 'development',
  
    target: 'electron-renderer',
  
    entry: [
      'react-hot-loader/patch',
      `webpack-dev-server/client?http://localhost:${port}/`,
      'webpack/hot/only-dev-server',
      path.join(__dirname, 'app/index.js')
    ],
  
    output: {
      publicPath: `http://localhost:${port}/dist/`,
      filename: 'renderer.dev.js'
    },
  
    module: {
      rules: [
        {
          test: /\.[jt]sx?$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
              presets: [
                '@babel/preset-env',
                '@babel/preset-typescript',
                '@babel/preset-react'
              ],
              plugins: [
                '@babel/plugin-transform-runtime',
                ["@babel/plugin-proposal-class-properties", { "loose": true }],
                'react-hot-loader/babel'
              ]
            }
          }
        },
        {
          test: /\.global\.css$/,
          use: [
            {
              loader: 'style-loader'
            },
            {
              loader: 'css-loader',
              options: {
                sourceMap: true
              }
            }
          ]
        },
        {
          test: /^((?!\.global).)*\.css$/,
          use: [
            {
              loader: 'style-loader'
            },
            {
              loader: 'css-loader',
              options: {
                modules: true,
                sourceMap: true,
                importLoaders: 1,
                localIdentName: '[name]__[local]__[hash:base64:5]'
              }
            }
          ]
        },
        // SASS support - compile all .global.scss files and pipe it to style.css
        {
          test: /\.global\.(scss|sass)$/,
          use: [
            {
              loader: 'style-loader'
            },
            {
              loader: 'css-loader',
              options: {
                sourceMap: true
              }
            },
            {
              loader: 'sass-loader'
            }
          ]
        },
        // SASS support - compile all other .scss files and pipe it to style.css
        {
          test: /^((?!\.global).)*\.(scss|sass)$/,
          use: [
            {
              loader: 'style-loader'
            },
            {
              loader: 'css-loader',
              options: {
                modules: true,
                sourceMap: true,
                importLoaders: 1,
                localIdentName: '[name]__[local]__[hash:base64:5]'
              }
            },
            {
              loader: 'sass-loader'
            }
          ]
        },
        // WOFF Font
        {
          test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
          use: {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/font-woff'
            }
          }
        },
        // WOFF2 Font
        {
          test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
          use: {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/font-woff'
            }
          }
        },
        // TTF Font
        {
          test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
          use: {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/octet-stream'
            }
          }
        },
        // EOT Font
        {
          test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
          use: 'file-loader'
        },
        // SVG Font
        {
          test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
          use: {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'image/svg+xml'
            }
          }
        },
        // Common Image Formats
        {
          test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
          use: 'url-loader'
        },
        // All files with a ".ts" or ".tsx" extension will be handled by "awesome-typescript-loader".
        {
          test: /\.tsx?$/,
          loader: "awesome-typescript-loader"
        },
        // All output ".js" files will have any sourcemaps re-processed by "source-map-loader".
        {
          test: /\.js$/,
          enforce: "pre",
          loader: "source-map-loader" }
      ]
    },
  
    plugins: [
      requiredByDLLConfig
        ? null
        : new webpack.DllReferencePlugin({
            context: process.cwd(),
            // eslint-disable-next-line global-require
            manifest: require(manifest),
            sourceType: 'var'
          }),
  
      new webpack.HotModuleReplacementPlugin({
        multiStep: true
      }),
  
      new webpack.NoEmitOnErrorsPlugin(),
  
      new webpack.EnvironmentPlugin({
        NODE_ENV: 'development'
      }),
  
      new webpack.LoaderOptionsPlugin({
        debug: true
      }),
  
      new ExtractTextPlugin({
        filename: '[name].css'
      })
    ],
  
    node: {
      __dirname: false,
      __filename: false
    },
  
    devServer: {
      port,
      publicPath,
      compress: true,
      noInfo: true,
      stats: 'errors-only',
      inline: true,
      lazy: false,
      hot: true,
      headers: { 'Access-Control-Allow-Origin': '*' },
      contentBase: path.join(__dirname, 'dist'),
      watchOptions: {
        aggregateTimeout: 300,
        ignored: /node_modules/,
        poll: 100
      },
      historyApiFallback: {
        verbose: true,
        disableDotRule: false
      },
      before() {
        if (process.env.START_HOT) {
          console.log('Starting Main Process...');
          spawn('npm', ['run', 'start-main-dev'], {
            shell: true,
            env: process.env,
            stdio: 'inherit'
          })
            .on('close', code =&gt; process.exit(code))
            .on('error', spawnError =&gt; console.error(spawnError));
        }
      }
    }
  });
  
  </code></pre>
  
  <p>Error message:</p>
  
  <pre><code>SyntaxError: Unexpected token {
  
  import { app, BrowserWindow } from 'electron';
         ^
  
      at Module._compile (internal/modules/cjs/loader.js:722:23)
      at Module._compile (C:\tool\node_modules\pirates\lib\index.js:99:24)
      at Module._extensions..js (internal/modules/cjs/loader.js:798:10)
      at Object.newLoader [as .js] (C:\tool\node_modules\pirates\lib\index.js:104:7)
      at Module.load (internal/modules/cjs/loader.js:645:32)
      at Function.Module._load (internal/modules/cjs/loader.js:560:12)
      at loadApplicationPackage (C:\tool\node_modules\electron\dist\resources\default_app.asar\main.js:109:16)
      at Object.&lt;anonymous&gt; (C:\tool\node_modules\electron\dist\resources\default_app.asar\main.js:155:9)
      at Module._compile (internal/modules/cjs/loader.js:786:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
  </code></pre>
  
  <p><strong>Update</strong>:</p>
  
  <p>As <strong>ford04</strong> said, need to use commonjs or es2015, because electron is worked only with es2015 standard. Need to set up babel presets/plugins either in .babelrc file or webpack config as well.</p>
  
  <p>tsconfig.js</p>
  
  <pre><code>{
    "compilerOptions": {
      "target": "es5",
      "lib": [
        "dom",
        "dom.iterable",
        "es2015",
        "es6",
      ],
      "outDir": "./dist",
      "allowJs": true,
      "skipLibCheck": true,
      "esModuleInterop": true,
      "allowSyntheticDefaultImports": true,
      "strict": true,
      "strictNullChecks": false,
      "forceConsistentCasingInFileNames": true,
      "module": "es2015",
      "moduleResolution": "node",
      "resolveJsonModule": true,
      "isolatedModules": true,
      "sourceMap": true,
      "noImplicitAny": false,
      "jsx": "react"
    },
    "include": [
      "./app"
    ],
    "exclude": [
      "node_modules",
      "**/node_modules/*",
      "dist"
    ]
  }
  </code></pre>
  
  <p>.babelrc I've replaced with babel.config.js according to <a href="https://github.com/electron-react-boilerplate/examples/blob/master/examples/typescript/babel.config.js" rel="nofollow noreferrer">electron-typescript</a></p>
  
  <pre><code>const developmentEnvironments = ['development', 'test'];
  
  const developmentPlugins = [
    require('react-hot-loader/babel'),
    require('@babel/plugin-syntax-typescript')
  ];
  
  const productionPlugins = [
    require('babel-plugin-dev-expression'),
  
    // babel-preset-react-optimize
    require('@babel/plugin-transform-react-constant-elements'),
    require('@babel/plugin-transform-react-inline-elements'),
    require('babel-plugin-transform-react-remove-prop-types')
  ];
  
  module.exports = api =&gt; {
  
    const development = api.env(developmentEnvironments);
  
    return {
      presets: [
        [
          require('@babel/preset-env'),
          {
            targets: { electron: require('electron/package.json').version },
            useBuiltIns: 'usage',
            corejs: 2
          }
        ],
        require('@babel/preset-typescript'),
        [require('@babel/preset-react'), { development }]
      ],
      plugins: [
  
        // Stage 0
        require('@babel/plugin-proposal-function-bind'),
  
        // Stage 1
        require('@babel/plugin-proposal-export-default-from'),
        require('@babel/plugin-proposal-logical-assignment-operators'),
        [require('@babel/plugin-proposal-optional-chaining'), { loose: false }],
        [
          require('@babel/plugin-proposal-pipeline-operator'),
          { proposal: 'minimal' }
        ],
        [
          require('@babel/plugin-proposal-nullish-coalescing-operator'),
          { loose: false }
        ],
        require('@babel/plugin-proposal-do-expressions'),
  
        // Stage 2
        [require('@babel/plugin-proposal-decorators'), { legacy: true }],
        require('@babel/plugin-proposal-function-sent'),
        require('@babel/plugin-proposal-export-namespace-from'),
        require('@babel/plugin-proposal-numeric-separator'),
        require('@babel/plugin-proposal-throw-expressions'),
  
        // Stage 3
        require('@babel/plugin-syntax-dynamic-import'),
        require('@babel/plugin-syntax-import-meta'),
        [require('@babel/plugin-proposal-class-properties'), { loose: true }],
        require('@babel/plugin-proposal-json-strings'),
        require('@babel/plugin-transform-runtime'),
  
        ...(development ? developmentPlugins : productionPlugins)
      ]
    };
  };
  </code></pre>
  
  <p>webpack.config.base.js</p>
  
  <pre><code>import path from 'path';
  import webpack from 'webpack';
  import fs from 'fs';
  import { dependencies as externals } from './app/package.json';
  
  export default {
    externals: [
      ...Object.keys(externals || {})
    ],
  
    module: {
      rules: [
        {
          test: /\.(js|jsx|tsx|ts)$/,
          exclude: /node_modules/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true
              }
            },
            'ts-loader'
          ]
        }
      ]
    },
  
    output: {
      path: path.join(__dirname, 'app'),
      libraryTarget: 'commonjs2'
    },
  
    resolve: {
      extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
      modules: [path.join(__dirname, 'app'), 'node_modules']
    },
  
    plugins: [
      new webpack.EnvironmentPlugin({
        NODE_ENV: 'production'
      }),
  
      new webpack.NamedModulesPlugin()
    ]
  };
  </code></pre>