L.Wiseby
L.Wiseby

Reputation: 39

Compiling Typescript with dependencies installed with yarn

I'm having some trouble compiling typescript code with references to yarn installed packages. Tsc cant find the packages because yarn uses the Plug And Play system.

The tsc error:

src/main.ts:1:36 - error TS2307: Cannot find module 'electron'.

1 import { app, BrowserWindow } from 'electron';
                                     ~~~~~~~~~~

src/main.ts:2:18 - error TS2307: Cannot find module 'node:path'.

2 import path from 'node:path';
                   ~~~~~~~~~~~

src/main.ts:8:42 - error TS2304: Cannot find name '__dirname'.

8     webPreferences: { preload: path.join(__dirname, 'preload.js') },
                                           ~~~~~~~~~

src/main.ts:23:7 - error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node`.

23   if (process.platform !== 'darwin') app.quit();
         ~~~~~~~

src/preload.ts:1:21 - error TS2307: Cannot find module 'node:process'.

1 import process from 'node:process';
                      ~~~~~~~~~~~~~~


Found 5 errors.

I'm totaly new to yarn and wanted to test it out.

Am I missing something in my configurations? Searched all over but couldn't find any documentation about using Typescript with yarn installed dependencies. Or do even the typescript compiler work with yarn? Maybe a command I left out to generate the node_modules? The whole point of using yarn was to get away from that.

tsconfig:

{
  "compilerOptions": {
    "lib": ["es2020", "DOM"],
    "module": "es2020",
    "moduleResolution": "Node",
    "target": "es2020",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "sourceMap": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "outDir": "dist",
    "baseUrl": ".",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": ["src/**/*"]
}


package.json:

{
  "name": "ElectroMega",
  "packageManager": "[email protected]",
  "private": true,
  "devDependencies": {
    "typescript": "^4.4.3"
  },
  "dependencies": {
    "@tsconfig/node14": "^1.0.1",
    "@types/node": "^16.9.6",
    "electron": "^14.0.1"
  }
}

I have my sourcefiles in a src folder in the root.

Upvotes: 3

Views: 6034

Answers (2)

Miks Silis
Miks Silis

Reputation: 1

FWIW, iamkneel's answer from above worked for my. Had an express app that I was using Typescript for and set it up with yarn. Setting nodeLinker: node-modules in the .yarnrc.yml file took care of the compile issue.

Upvotes: 0

L.Wiseby
L.Wiseby

Reputation: 39

As my comment mentions in the original question, from the yarn documentation:

TypeScript uses its own resolver as well. In this case the situation is a bit more complex - the TS team has some concerns about allowing third-party hooks inside the tsc compiler, meaning that we can’t work with it at the moment. That being said, TypeScript isn’t only tsc and as such we’ve been able to add PnP support to the popular ts-loader - meaning that as long as you compile your TypeScript through Webpack, everything works well! Consult the dedicated section about it for more information.

To enable yarn package resolution when using Typescript you have to use webpack with ts-loader. This is how I resolved it.

  • install the neccessary dependencies:

npm install webpack webpack-cli pnp-webpack-plugin ts-loader

  • Create a 'webpack.config.js' file in your project root directory with the following content:
const path = require('path');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

const commonConfig = {
  mode: 'development',
  devtool: 'source-map',
  plugins: [
    new NodePolyfillPlugin(),
  ],
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist'),
  },
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
    plugins: [PnpWebpackPlugin],
  },
  resolveLoader: {
    plugins: [PnpWebpackPlugin.moduleLoader(module)],
  },
};

module.exports = [
  Object.assign(
    {
      target: 'electron-main',
      entry: { main: './src/main.ts' },
    },
    commonConfig
  ),
  Object.assign(
    {
      target: 'electron-renderer',
      entry: { preload: './src/preload.ts' },
    },
    commonConfig
  ),
];
  • I updated my package.json with scripts to run webpack:
{
  "name": "ElectroMega",
  "packageManager": "[email protected]",
  "private": true,
  "scripts": {
    "build": "webpack",
    "prestart": "yarn run build",
    "start": "electron ./dist/main.js"
  },
  "devDependencies": {
    "html-webpack-plugin": "^5.3.2",
    "node-polyfill-webpack-plugin": "^1.1.4",
    "pnp-webpack-plugin": "^1.7.0",
    "ts-loader": "^9.2.6",
    "typescript": "^4.4.3",
    "webpack": "^5.54.0",
    "webpack-cli": "^4.8.0"
  },
  "dependencies": {
    "@tsconfig/node14": "^1.0.1",
    "@types/node": "^16.9.6",
    "electron": "^14.0.1"
  }
}
  • Then you should be able to build your code with the command:

yarn build

My solution was a result of following the webpack GettingStarted section that explained much of the troubles I had, and the basics of using webpack.

Upvotes: 1

Related Questions