Leveraging NPM workspaces in combination with Expo and Typescript

I'm struggling to incorporate NPM 7 workspaces into a Typescript Expo project. The goal is to maintain the standard Expo structure, with the root App.tsx file, while segregating certain code sections into workspaces.

I'm facing challenges compiling the TS code within the workspaces. Despite numerous attempts to configure the TS and/or Webpack settings, I haven't been successful. Here's a simplified file layout to replicate the issue:

package.json
tsconfig.json
App.tsx
/packages
  /core
    index.ts
    package.json

The crucial part of the main ./package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "workspaces": [
    "packages/*"
  ],
  "scripts": {...},
  "dependencies": {...},
  "devDependencies": {...},
  "private": true
}

The minimal ./tsconfig.json

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true
  }
}

The simple ./packages/core/package.json

{
  "name": "core",
  "private": true
}

In ./packages/core/index.ts, there's just an exported log() function for demonstration purposes

export function log(s: string) {
  console.log(s)
}

Lastly, in ./App.tsx, the function is imported and called

import { log } from 'core'
log('hello')
//...

Compilation Issue

When attempting to build for web (e.g., using expo build:web), the following error occurs:

✖ Expo Webpack
  Compiled with some errors in 1.62s

Failed to compile.

[path]/node_modules/core/index.ts 1:21
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export function log(s: string) {
|   console.log(s)
| }

This error is expected since the /node_modules directory is intentionally excluded.

Therefore, my query is what measures should be taken to successfully compile the workspaces code? Ideally, it should be seamlessly integrated, akin to regular project files without precompilation. Is this attainable?

Failed Resolution Attempts

I primarily focused on altering the tsconfig to resolve the issue, although its impact remains questionable

#1

Tried adding

"include": ["./node_modules/core"],
in ./tsconfig.json. However, it proved ineffective as the error persisted.

#2

Created /packages/core/tsconfig.json containing the composite option:

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "composite": true
  }
}

Referenced this in the root tsconfig.json:

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true
  },
  "references": [{ "path": "./node_modules/core" }]
  // or even with:
  "references": [{ "path": "./packages/core" }]
}

Yet, these efforts didn't yield any positive outcome as the same error persisted.

Your assistance is greatly appreciated.

Answer №1

I managed to come up with a solution that, while not perfect, is getting the job done. I simply configured Webpack to compile my packages/* (as symbolic links in the node_modules directory).

To begin, I installed:

$ npm i -D ts-loader@8 <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0d7a686f7d6c6e664d3923393e3d">[email protected]</a>

Paying attention to versions is crucial here to maintain consistency with Expo 41.

In addition, I modified the package name (in /packages/core/package.json) to something like @workspace/core, ensuring all custom packages are located within the node_modules/@workspace directory.

This adjustment also simplifies our configuration.

Executing $ expo customize:web is essential for tweaking the webpack configuration. This command will generate a webpack.config.js file.

The configuration can be personalized as shown below:

const createExpoWebpackConfigAsync = require('@expo/webpack-config')

module.exports = async function (env, argv) {
  const config = await createExpoWebpackConfigAsync(env, argv)

  config.module.rules = [
    {
      // Using the @workspaces prefix eases the identification of renamed packages.
      test: /node_modules\/@workspaces\/(.*)\.ts$/, 
      use: [
        {
          loader: 'ts-loader',
          // Enabling ts-loader to compile within node_modules
          options: { allowTsInNodeModules: true },
        },
      ],
    },
    ...config.module.rules,
  ]

  return config
}

There may be a more streamlined solution out there, but for now, this setup will suffice.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing the issue with npm install packages not functioning properly?

Currently, I am in the process of setting up and deploying a particular git repository locally: https://github.com/maxie112/gatsby-ecommerce-theme I am strictly adhering to the instructions provided for Mac OS. Here are the encountered error logs; maxden ...

Guide to automatically installing @types for all node modules

As a newcomer to Typescript and NodeJs, I have been experiencing errors when mentioning node modules in my package.json file and trying to import them. The error messages I always encounter are as follows: Could not find a declaration file for module &apos ...

The value of this.$refs.<refField> in Vue.js with TypeScript is not defined

During the process of converting my VueJs project to TypeScript, I encountered an error related to TypeScript. This issue arises from a component with a custom v-model implementation. In the HTML, there is an input field with a 'plate' ref that ...

Exploring the Realm of Javacript Template Literal Capabilities

Is it possible to define a variable inside a template literal and then utilize it within the same template? If this isn't feasible, it appears to be a significant feature that is lacking. const sample = tag` some random words, ${let myvar = 55} addit ...

Is it possible to configure npm install to install "bin" executables directly into the local node_modules directory (rather than the .bin directory)?

In my Node project, I am able to package it into a tarball using npm pack, and then install it in another directory for testing purposes. This allows the files specified in the "bin" section of my package.json file to be symlinked correctly into the node_m ...

Retrieve the part of a displayed element

Presently, I am developing a modal system using React. A button is located in the sidebar and the modal is represented as a div within the body. In the render function of the main component of my application, two components are being rendered: MyModal M ...

Transforming an array of flat data into a hierarchical tree structure

I'm facing a challenge with my script. I have an Array of FlatObj and some rules, and I need to create a converter function that transforms them into TreeObj. The Rules are: If an object has a higher depth, it should be a child of an object with a l ...

Tips for accessing the 'index' variable in *ngFor directive and making modifications (restriction on deleting only one item at a time from a list)

Here is the code snippet I'm working with: HTML: <ion-item-sliding *ngFor="let object of objectList; let idx = index"> <ion-item> <ion-input type="text" text-left [(ngModel)]="objectList[idx].name" placeholder="Nam ...

importance of transferring information in URL encoded form

Recently, I started learning about node.js and API development. During a presentation, I was asked a question that caught me off guard. I had created a REST API (similar to a contact catalog) where data was being sent through Postman using URL encoded PO ...

Transforming JSON in Node.js based on JSON key

I am having trouble transforming the JSON result below into a filtered format. const result = [ { id: 'e7a51e2a-384c-41ea-960c-bcd00c797629', type: 'Interstitial (320x480)', country: 'ABC', enabled: true, ...

What is the process of incorporating npm packages into a .NET Core project within Visual Studio 2019?

As I venture into the world of front end development using React in conjunction with .NET Core for backend, I find myself grappling with new tools and technologies. My task is to utilize Visual Studio 2019 for working with .NET Core, a development enviro ...

utilize makeStyles to modify button text color

Initially, my button was styled like this: style={{ background: '#6c74cc', borderRadius: 3, border: 0, color: 'white', height: 48, padding: '0 30px', }}> It worke ...

Using TypeScript to create a state object in Koa

I am currently utilizing Koa () as the framework for my backend, which consists of Node.js + TypeScript. Koa permits and recommends using the built-in `ctx.state` to store and pass data between different middleware functions. I have been adhering to this ...

Tips for associating an id with PrimeNg menu command

Within my table, I have a list of items that I would like to enhance using PrimeNg Menu for dropdown menu options. The goal is to enable navigation to other pages based on the selected item id. When a user clicks on a menu item, I want to bind the id of th ...

What is the best way to loop through a formarray and assign its values to a different array in TypeScript?

Within my form, I have a FormArray with a string parameter called "Foo". In an attempt to access it, I wrote: let formArray = this.form.get("Foo") as FormArray; let formArrayValues: {Foo: string}[]; //this data will be incorporated into the TypeScript mod ...

Implement a class in Typescript that allows for the addition of properties at runtime

I'm currently in the process of incorporating Typescript definitions into an existing codebase that utilizes the Knockout library. Within the code, there is a prevalent pattern that appears as follows: interface SomeProperties { // Assorted prope ...

What steps should I take to resolve the issue of my endpoint failing to accept POST requests?

I am in the process of developing a customized API, with an endpoint that is specified as shown below: https://i.stack.imgur.com/sZTI8.png To handle the functionality for this endpoint, I have set up a Profiling Controller. Inside my controller directory ...

The SideNav SpyOn feature failed to locate the specified method

In the test project I am working on, there is a side navigation menu. I need to create a simple test to verify that when I click the button, the sidenav opens or closes. The AppComponent interacts with the sidebar through its dependency, sidenavbar. it(&a ...

What is the location of the storage for npm modules?

Currently, I am in the process of learning node.js and I have a couple of inquiries: Can you please explain where npm modules are stored? 2. Just to clarify, is node.js considered a database technology? 3. Lastly, do you need an internet connection in ...

What about a toggle for read-only TypeScript everywhere? (parameters in functions)

Is there a method, whether through a macro library, an eslint rule, a tsconfig setting, a special global.d.ts file, or some other means, to automatically set function arguments as readonly by default? // I wish for the compiler to transform this: functio ...