Electron + Typescript + Webpack: Boilerplate Example

Mark Dolbyrev picture Mark Dolbyrev · Feb 25, 2018 · Viewed 10.9k times · Source

I don't know how to start the question, but the main problem is that I can't make the 3 technologies work together: Electron + Typescript + Webpack

I've encountered few boilerplates, but in them either the whole typescript is built with tsc (instead of Webpack), or only render-part is built with Webpack, and the main-process (main.js) part is written in pure js.

So I was wondering if anybody has or knows where to find a boilerplate project to start the new Electron + Typescript + Webpack project?

As far as I understand it should be configured to build separately main-process and render-process parts of the application (probably, their configs might be different).

Thanks in advance.

Answer

Tarun Lalwani picture Tarun Lalwani · Mar 1, 2018

I have added a sample template/boilerplate on below link

https://github.com/tarunlalwani/electron-webpack-typescript-boilerplate

So the idea is to break the code in 3 folders

src
|-- common
|-- main
|-- renderer

The code for the main electron process will go into main folder and for the UI/renderer will go into the renderer folder.

Now you want to use TypeScript in both and have 2 webpack config, one for bundling the main and one for bundling the renderer.

const path = require('path');

console.log(__dirname);
let common_config = {
  node: {
    __dirname: true
  },
  mode: process.env.ENV || 'development',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: [
          /node_modules/,
           path.resolve(__dirname, "src/ui")
        ]
      }
    ]
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js' ]
  },
};

module.exports = [
  Object.assign({}, common_config, {
    target: 'electron-main',
    entry: {
      renderrer: './src/main/index.ts',
    },
    output: {
      filename: '[name]-bundle.js',
      path: path.resolve(__dirname, 'src/main/dist')
    },
  }),
  Object.assign({}, common_config, {
    target: 'electron-renderer',
    entry: {
      ui: './src/renderer/index.ts',
    },
    output: {
      filename: '[name]-bundle.js',
      path: path.resolve(__dirname, 'src/renderer/dist')
    },
  })
]

Another issue that one faces is that __dirname becomes / if do nothing about it. So we include below in our webpack config

  node: {
    __dirname: true
  },

This make sure that a relative path is available. Now we can use os.cwd() in dev environment and use process.resourcePath in production. See below thread for more details

How to run and pack external executable using Electron?

The target for both the webpack config needs to be different. So for main we use electron-main and for renderer we use electron-renderer

The tsconfig.json needs to be different for both main and renderer and should excluded each other. So we use

renderer/tsconfig.json

{
    "compileOnSave": false,
    "compilerOptions": {
        "target": "es2015",
        "moduleResolution": "node",
        "pretty": true,
        "newLine": "LF",
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "sourceMap": true,
        "skipLibCheck": true,
        "allowJs": true,
        "jsx": "preserve"
    },
    "exclude": [
      "node_modules",
      "src/main"
    ]
}

main/tsconfig.json

{
    "compileOnSave": false,
    "compilerOptions": {
        "target": "es2015",
        "moduleResolution": "node",
        "pretty": true,
        "newLine": "LF",
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "sourceMap": true,
        "skipLibCheck": true,
        "allowJs": true,
        "jsx": "preserve"
    },
    "exclude": [
      "node_modules",
      "src/renderer"
    ]
}

The final main thing is your package.json, which is below

{
  "name": "boilerplate",
  "version": "1.0.0",
  "main": "src/main/dist/renderrer-bundle.js",
  "license": "MIT",
  "scripts": {
    "start": "npm-run-all build run-electron",
    "build": "webpack --config webpack.config.js",
    "run-electron": "electron ."
  },
  "dependencies": {
    "electron": "^1.8.2",
    "jquery": "^3.3.1",
    "typescript": "^2.7.2",
    "webpack": "^4.0.1"
  },
  "devDependencies": {
    "@types/electron": "^1.6.10",
    "@types/jquery": "^3.3.0",
    "@types/node": "^9.4.6",
    "html-webpack-plugin": "^2.30.1",
    "npm-run-all": "^4.1.2",
    "ts-loader": "^4.0.0",
    "tslint": "^5.9.1",
    "webpack-cli": "^2.0.9"
  }
}

This is should get your started and then you can add things link tslint, jslint as you go along