Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Electron + Typescript + Webpack: Boilerplate Example

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.

like image 823
Mark Dolbyrev Avatar asked Feb 25 '18 11:02

Mark Dolbyrev


2 Answers

Tarun Lalwani's answer was pretty great, but I wanted to offer a modern alternative to anyone who stumbles across this page.

https://github.com/hellosoftware-io/electron-typescript-react-mui

It uses electron 15, typescript, and webpack 5. It also supports live reloading as requested by netlander.

My strategy was to setup the file structure like this

static
src
|-- main
|-- renderer

The static folder holds images, main holds electron content, and renderer holds the js (currently built with react).

I'm also using just one tsconfig and two webpack configs to try and simply things a bit.

I hope this helps anyone who stumbles across this post :)

like image 82
Xhale Avatar answered Oct 24 '22 09:10

Xhale


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

like image 42
Tarun Lalwani Avatar answered Oct 24 '22 10:10

Tarun Lalwani