Monorepo and problem with building packages - node.js

I try to build modular React application using monorepository (workspaces) - in root folder I have package.json:
{
"private": true,
"workspaces": ["shared/react-components", "client/react-app"],
"scripts": {
"start": "yarn --cwd shared/react-components build && yarn --cwd client/react-app start"
}
}
I want to include shared/react-components (named e.g. as #shared/react-components), into client/react-app but before I need to compile shared module, and at this place I get nasty error:
Error: 'default' is not exported by ../../node_modules/deepmerge/dist/cjs.js, imported by src/styles/dark.ts
I ran yarn install before so deepmerge is available in /node_modules. If I remove workspaces configuration and run: yarn install && yarn build in shared/react-components everything works, so it seems that problem is in workspaces configuration.
Build script in shared/react-components is: rollup -c
Any idea what could be missing?

It turned out to be a problem was with deepmerge package and TSX, the long thread about problems with importing can be found here: https://github.com/TehShrike/deepmerge/issues/87 I replaced it with lodash merge, and my packages were build again.

Related

Creating StoryBook build using cross-env

We're using Storybook platform to build UI components and pages in isolation. According to Storybook documentation, an npm package can be published with npm publish command after it's been built. But first they say that it needs to be built with this command:
{
"scripts": {
"build": "cross-env BABEL_ENV=production babel src -d dist"
}
}
This creates dist folder which looks like this:
My issue is that it doesn't include any .css or .json files that are part of the project. So I have to move them there manually.
Any idea how can I configure the project to include them automatically so I don't have to do it each time I run the build command?

Configure Mocha sidebar for typescript test file

How can I configure Mocha sidebar for my project?
My test files are located in this path: /src/Gamma.Tests/*.ts.
Also I set these in settings.json file:
"mocha.files.glob": "src/Gamma.Tests/**/*.ts",
"mocha.requires": [
"ts-node/register"
]
I have installed these packages already:
npm install typescript --save-dev
npm install ts-node --save-dev
npm install -g ts-node
npm install -g typescript
The error in VSCode:
Failed to run Mocha due to error message:
" Cannot find module 'ts-node/register' Require stack:
c:\Users\rouhi.vscode\extensions\maty.vscode-mocha-sidebar-0.22.2\lib\worker\findtests.js
" error trace can be found in the ouput channel .
for more help:
How can I solve this problem?
Notice:
in package.json file:
"scripts": {
"test": "mocha -r ts-node/register src/Gamma.Tests/**/*.ts",
"start": "tsc && node ./build/server.js"
},
There is no problem, when I run npm run test
Solution for Mocha Test Explorer
I had the same problem using mocha sidebar. Intrigued by this demo, I installed the Mocha Test Explorer extension and faced the same problem (among others).
It didn't work for me since I had the whole "backend" project in a subfolder of the project root. The solution for me was to set up a multi-root project in VSCode:
Click on File -> Add Folder to Workspace
Choose your subfolder, e.g. backend
Click on File -> Save Workspace As and save the workspace.code-workspace file to the .vscode folder in your project root.
In your subfolder (e.g. backend), create a new folder .vscode and place a new settings.json file with the following content:
{
"mochaExplorer.files": "test/**/*.ts",
"mochaExplorer.require": "ts-node/register"
}
If you still encounter problems with ts-node/register, this post on StackOverflow might be useful. For tips using a multi-root workspace in VSCode, see this great blog post.

NPM Run Build Always Builds Production and Never Development

On an inherited project I have, I am trying to get the build command to build a version other than Production.
I have attempted to change the alias in the script section in package.json to pass in extra variables such as --dev and --configuration=dev to no avail.
The project has these json data files:
env.dev
env.development
env.production
with the package.json has this build alias build:dev which I run npm run build:dev:
"scripts": {
"start": "NODE_ENV=dev && react-scripts start",
…
"build:dev": "npm run build --dev --configuration=dev && react-scripts build"
}
This works and builds, but for production only which I verify when I view the resultant files.
If I remove the file env.production from the directory and run the build command, it fails with:
Creating an optimized production build...
Failed to compile.
Module not found: Error: Can't resolve 'polyfills' in 'C:\Work\MyProj\WebSiteName\src'
which just informs me that it can alias polyfills found in the env.production file for the location NODE_PATH=src/.
Thoughts?
you need to set the env. variable like you do in "start" before calling the build command.
"build:dev": "NODE_ENV=dev npm run build --dev --configuration=dev && react-scripts build"

How do I deploy my Typescript Node.js app to Heroku?

When testing locally I was previously running:
"build-live": "nodemon --exec ./node_modules/.bin/ts-node -r dotenv/config -- ./index.ts"
I then figured my Procfile should be something like:
web: ./node_modules/.bin/ts-node -- ./index.ts
But it says module 'typescript' not found, even when it is in package.json. I read in a few places that ts-node is not the way to go to deploy to Heroku, so I am not sure what to do.
UPDATE: I think I am supposed to compile it, so I tried:
web: ./node_modules/.bin/tsc --module commonjs --allowJs --outDir build/ --sourceMap --target es6 index.ts && node build/index.js
This succeeds, however when actually running it, a bunch of the libs I'm using get "Cannot find module '...'".
Alternatively you can have the TypeScript compile as a postinstall hook and run node build/index.js as the only Procfile command:
Your package.json should contain a postinstall hint that gets executed after npm install and before the node process launches:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
You can then leave your Procfile as is:
web: npm start
This 'build on deploy' approach is documented by Heroku here.
The command you've given Heroku is to launch the web "process" by compiling index.ts and dependencies and starting node at index.js. Depending on how things are timed, index.js might or might not exist at the time node starts.
You need to already have your sources compiled by the time you want to start your app. For example, web should just be web: node index.js or similar.
Each build process is different, so you need to figure that out for your own setup. But, suppose you have a classical setup where you push to git and then Heroku picks up that change and updates the app with the new slug. You could just compile things locally and include index.js and any other build output in the repository, for it to be available in the slug for Heroku to use.
A better approach is to use a build server which has an integration with Heroku. After you do the build there, configure it to send the build results to Heroku. Travis has a straighforward setup like this. This way you don't need to include build outputs in your repository, which is considered an anti-pattern.
On a sidenode, try using a tsconfig.json to keep the tsc configuration. It will save you from having to write such long command lines all over the place.
Fabian said that we could do something like:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
As of me writing this, I tested this and can state: postinstall is not required since build script is ran by Heroku. If you want to do it without build script, then you can use heroku-postbuild which will run after dependencies are installed there you run tsc to compile.
My problem was about missing Typescript npm modules. The Typescript compiler tsc was not found when deployed the app to Heroku.
The Heroku deploy process (rightly) does not install development dependencies, in my case the Typescript module was part of devDependencies and thus the tsc command was not running on the Heroku platform.
Solution 1
Add typescript to dependencies: npm i typescript -s
Solution 2
Open Heroku console:
Select console type:
Run the command npm i typescript && npm run tsc
Install typescript as a dev dependency (cf. https://www.typescriptlang.org/download). Once built, your app does not need typescript anymore!
npm install -D typescript
Then in your package.json:
{
"main": "index.js", // <- file will be generated at build time with `tsc`
"scripts": {
"build": "tsc",
"start": "node ."
"start:dev": "ts-node index.ts" // idem, install ts-node as a dev dependency
}
}
The key point here is "build": "tsc".
Why?
Heroku does install all dependencies during build and remove the dev dependencies before the app is deployed (source here).
Node.js deployments will automatically execute an app’s build script during build (since March 11. 2019 source here)
In package.json
"scripts": {
"tsc": "./node_modules/typescript/bin/tsc",
"postinstall": "npm run tsc"
},
Works for me for Heroku deployment.
Installing typescript npm install -D typescript and writing tsc in the build script "build": "tsc", does not work for me. Also, try to run npm i typescript && npm run tsc in the Heroku console which also does not work.
In my case, I remove some dependencies from "devDependencies" to "dependencies", so it goes like this:
"dependencies": {
// The other dependencies goes here, I don't touch them.
// But all TS dependencies I remove to here.
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3",
"ts-loader": "^8.0.18"
},

How to save the installation of global package using package.json?

How to save the installation of global package using package.json?
I couldn't find any good solutions but I did this like below:
In package.json I added the following:
"scripts": {
"preinstall": "npm install babel babel-cli -g"
},
It would run and install the above packages globally before installing all the dependencies and devDependencies in package.json.
But the problem would be that I would not be able to find out, are those packages installed globally in any of the machines.
Please help, if anyone have any better solution of this.
It's a bad practice to force global install of a module. You can put babel and babel-cli in your devDependencies and then use them in your npm scripts :
{
"build" : "babel src -d build"
},
"devDependencies": {
"babel-cli": "^6.18.0"
}
If you are looking to run your package via CLI, you need to set up using bin approach.
Here's one of my libraries for example, fol. It is meant to be ran via command line only.
At the most minimal setup, you would wire both main and bin to the same JS file, for example, adding the following in package.json:
"main": "./bin/fol.js",
"bin": {
"fol": "./bin/fol.js"
},
Then, put the files into bin folder for the same of consistency, everybody will recognise that's CLI app stuff if it's in /bin/.

Resources