How can I make Heroku install devDependencies? - heroku

I would like to have Heroku build my app after I push it so that I don't have to push the build folder up every time I make a change. However Heroku only installs the dependencies from the package.json and grunt (my build tool) and all of its components are in devDependencies. I would like to keep them there where they belong. What's the workaround here?

UPDATE: as pointed out in the comments this is no more needed because since 2018 heroku changed its default behaviour and dev dependencies are automatically installed
ORIGINAL ANSWER
Heroku by default installs only the production dependencies, ignoring the development dependencies under devDependencies.
Setting the npm production variable to false do the trick:
heroku config:set NPM_CONFIG_PRODUCTION=false
More info are available at the Heroku Node.js Support page.

Keeping NPM_CONFIG_PRODUCTION true, I used Heroku's script hooks:
"scripts": {
...
"heroku-prebuild": "export NPM_CONFIG_PRODUCTION=false; export NODE_ENV=; NPM_CONFIG_PRODUCTION=false NODE_ENV=development npm install --only=dev --dev",
"heroku-postbuild": "export NPM_CONFIG_PRODUCTION=true; export NODE_ENV=production;",
...
},
(Finally) worked for me.

scripts": {
...
"heroku-prebuild": "npm install --only=dev"
}
This was enough for me. Thanks to PixnBits for the hint about heroku-prebuild.
Also - my problem was with babel. I ended up moving babel-preset-es2015 and other presets into dependencies otherwise babel complained about presets.
Update: 8/11/2017 I've been having trouble with this. It seems like things have changed (and npm is on 5.3 now). But what I see is that the heroku-prebuild script is getting run, and then the post-install script is getting run (but I was only trying to install -dev).
So what I have been doing that works is to just run:
heroku config:set NPM_CONFIG_PRODUCTION=false
And just leave it set that way. I'd love a better solution.

you can use this in your build script "build": "npm install --only=dev" should in case you still want to perform more operations e.g transpiling your code with babel you can do something like this "build": "npm install --only=dev && babel src --out-dir dist --copy-files"

To unintall dependencies you need to do these
Update NPM_CONFIG_PRODUCTION
heroku config variable set
NPM_CONFIG_PRODUCTION=false
Add heroku-prebuild:
scripts": {
...
"heroku-prebuild": "npm install"
}
or
scripts": {
...
"heroku-prebuild": "npm install --only=dev"
}

Since 1 March 2018 Heroku installs devDependencies by default, and then prunes them after the build step is done:
By default, Heroku will install all dependencies listed in
package.json under dependencies and devDependencies.
After running the installation and build steps Heroku will strip out
the packages declared under devDependencies before deploying the
application.
Heroku uses the lockfiles, either the package-lock.json or yarn.lock,
to install the expected dependency tree, so be sure to check those
files into git to ensure the same dependency versions across
environments.
Link

I found this highly confusing. Even though Heroku says that their default since 2018 is to install all dependencies, they also set the env var NODE_ENV=production by default. This is good because it causes/allows for pruning, but it is bad because it means NPM will not install devDependencies.
To avoid this without messing with environment variables and their possible side effects, we can append --production=false to npm and it will install dependencies and devDependencies.
In our case, in package.json in scripts we have a line:
"install": "npm i --prefix ... --production=false"
My answer similar to others above with the additional references that seem to explain why it's not actually working by default like Heroku suggests.

Related

Unknown file extension ".ts" cypress.config.ts on CI

When I run npm run cypress:run in my GitLab CI env I get the error:
Your configFile is invalid: //WebApp/cypress.config.ts
It threw an error when required, check the stack trace below:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for //WebApp/cypress.config.ts
test:cypress:
image:
name: cypress/included:10.3.1-typescript
entrypoint: ['']
stage: test
script:
- yarn install --frozen-lockfile
- cd WebApp
- npm run cypress:run
rules:
- *branch
If I run npm run cypress:run from the WebApp folder (where cypress.config.ts is in the root) locally I have no issue. Also no issues when I do an npx cypress:run
However, if I run npx cypress run --config-file WebApp/cypress.config.ts from the parent folder locally I do get the error:
Unknown file extension ".ts"
Any ideas why locally Cypress is working but on the CI the config file is incorrect?
This still seems to be an issues today for LTS 10.10.0
Changing the fresh install cypress.config.ts -> cypress.config.js
and use require like so proved successful.
module.exports = require('cypress').defineConfig({ component: {
devServer: {
framework: "create-react-app",
bundler: "webpack",
},
},
});
I updated this github issue with some more information.
This will be because you have typescript installed globally on your machine so it will work ok locally but not in CI.
Essentially typescript has to be in the folder from where the cypress command is run for it to detect typescript properly.
I went with:
script:
- npm install --global serve
- serve ./build --listen 3000 &
- rm package*
- npm install #percy/cypress typescript
- npm install --global #percy/cli
- percy exec --verbose -- cypress run
Just installing the bare minimum to run the e2e tests ./build is an artifact from another run and percy is really great if you have not used it before.
I am late here, i had similar issue. The del package to delete passed videos was the culprit for me. In the CI environment, it requested to install the del package separately, but in my cypress.config.ts, i was directly able to import del package which was served from third party.
I wanted to install the exact del package in my case and that solved the problem. Del package has its limitations, rimraf solved my issue.
https://www.npmjs.com/package/rimraf
It looks like it's about the version. This might be hepful GitHub
I have tried all different ways suggested in the GitHub issue that
user18025789 linked, but nothing helped. Then I tried switching the config file from .ts to cypress.config.js and it started to work (syntax needed to be updated to JavaScript as well). I have no idea why.
I came across this issue because Typescript was not installed in my Cypress container. When ts-node doesn't have access to typescript, it's require behaves like the native "require", which is why you're seeing the error.
I don't know enough about your specific setup to recommend a solution, but for me I was able to run npm i and mount the volume in the cypress container before running the tests. Another option could be to create a new Dockerfile to extend the base Cypress image with typescript included in the build.
If working on a monorepo and mounting only the app/package folder to test into the cypress docker image, not all dependencies are available within this directory.
To fix this mounting, the whole workspace does the job:
cypress:
image: cypress/included:10.11.0
# …
working_dir: /workspace/app
volumes:
- ..:/workspace
I started facing this issue, suddenly, My solution wasrm -rf node_modules package-lock.jsonnpm i I already had the cypress.config.ts file, so cypress test runner picked it up, when I rannpx cypress open

How to import a forked npm package of Github in Laravel Mix?

In package.json, I have:
"vue-search-select": "github:my-github-account/vue-search-select"
And then run npm install, no error.
In app.js, I try to import the forked package:
import { ModelSelect } from 'vue-search-select';
When I run npm run watch, got the below message:
Module not found: Error: Can't resolve 'vue-search-select'
UPDATE:
I compared the original version and forked version in node_modules: Original contains dist folder but forked version don't have. In github, the original one also don't have this folder. And dist is included in .gitignore.
I understand that, for package.json GitHub URL, As of version 1.1.65, you can refer to GitHub URLs as just foo:user/foo-project, as seen here.
But I would still recommend a more complete URL instead:
git+ssh://user#hostname:project.git#commit-ish
git+ssh://user#hostname/project.git#commit-ish
git+http://user#hostname/project/blah.git#commit-ish
git+https://user#hostname/project/blah.git#commit-ish
That way, you control the scheme (HTTPS or SSH) and can check which credentials (cached username/password for HTTPS or private key for SSH) is used.
The OP Wilson comments in the discussion that adding dist/ to the repo could be an option, as in here.
A prepare script can be declared in the package.json, such as this one.
"scripts": {
"build": "tsc",
"prepare": "npm run build"
},
As noted in Wilson's answer
the important thing is that the prepare script is added in forked package, not in the project that using the package.
Finally, I found a solution:
Add "prepare": "npm run lib:build" (or something else depends on the package how to build, can check it in package.json) to scripts of package.json to the forked package. And push to github.
Then, in the project that using the forked package, just keep "package-name": "github:my-github-account/package-name" in package.json and run npm install again. No other changes.

Why isn't my clojure/cljs app deploying on Heroku?

I'm trying to deploy my app to heroku and I keep getting this error:
The required namespace "react" is not available, it was required by "reagent/core.cljs".
But I have
"react": "17.0.2-0",
"react-dom": "17.0.2-0",
"react-highlight.js": "1.0.7",
all in my package.json and I also put
[cljsjs/react "17.0.2-0"]
[cljsjs/react-dom "17.0.2-0"]
in my project.clj. I also did npm install react. I'm not sure what I'm doing wrong?
It compiles fine using shadow-cljs to my localhost, but it won't compile when I try to push to heroku. Any idea what I'm missing?
Editing to add some more details:
I made a bin/build file based on this blog post, even though I'm not using Fulcro: https://folcon.github.io/post/2020-04-12-Fulcro-on-Heroku/
I created a bin/build file that say this:
#!/usr/bin/env bash
npm install
npx shadow-cljs release main
clojure -A:depstar -m hf.depstar.uberjar fulcro.jar
I added this to my shadow-cljs.edn file:
;; v-- and this!
:release {:compiler-options {:optimizations :advanced}}}
And it also said to add something to my deps.edn file, but I don't have one so I didn't.
I also did the buildpack step to add the clojure and nodejs buildpacks, although I'm not using nodejs to my knowledge.
I had the same problem, it was very easy to fix.
You need to first specify buildpacks nodejs, and after it only clojure.
from here:
npm install react react-dom create-react-class

Is it possible to disable ESLint when running npm run build for a React app?

I have an app initiated using Create React App, so npm run build runs react-scripts build. I recently installed prettier and so added a .eslintrc.json file to the project root to load the prettier plugin. npm run build works as expected locally, but, when deploying the app to Heroku, npm run build tries to run ESLint and fails because the plugins are devDependencies rather than dependencies.
Failed to load plugin 'prettier' declared in '.eslintrc.json': Cannot find module 'eslint-plugin-prettier'
From prior wrangling with a similar issue, I know that I can set NPM_CONFIG_PRODUCTION=false in Heroku so that it will install devDependencies, which actually does resolve the deployment issue. Nevertheless, I'm curious to learn if there's another solution that doesn't require setting NPM_CONFIG_PRODUCTION=false.
Is it possible to prevent npm run build in this scenario from running ESLint altogether or to prevent it from trying to access the plugins specified in .eslintrc.json? I acknowledge that adding .eslintrc.json to .gitignore is one solution, but I want the ESLint configuration in my repo.
you can run "npm run eject" to generate webpack configuration files, and then modify "webpack.config.js",delete the eslint configuration

Configure node npm package.json so that "npm test" works on both unix and windows

I have developed a node.js npm module, developing under Windows. Today I wrote some Mocha tests. After many struggles, it seemed that for npm test to work, package.json had to look like this: (there may be other options???)
"scripts": { "test": "node node_modules/mocha/bin/mocha" }
instead of what's in all the Unix based books,
"scripts": { "test": "./node_modules/.bin/mocha" }
How can I set package.json up to work on both Windows and Unix? I'm assuming that Travis-CI runs Unix, so, should I link the build to that, it will blow up with the Windows version.
I found a two year old thread where somebody requested a feature for exactly this. That thread seemed to die out. This SO question seems to be close, but it isn't exactly what I want and, frankly, I can't understand the answer. :-( Can anybody clarify?
For the time being, I am going
"scripts": {
"test": "node node_modules/mocha/bin/mocha",
"testOnUnixUseThis" : "./node_modules/.bin/mocha (I think)",
"testOnWindowsUseThis" : "node node_modules/mocha/bin/mocha"
},
Unfortunately, you cant go npm test testOnWindowsUseThis or npm testOnWindowsUseThis. And it doesn't fix the Travis-CI issue. But at least a person who downloads the module can (hopefully) see what is going on.
Any better ideas? Am I the only person still developing under Windows??? :-)
I've always been able to npm install -g mocha or npm install mocha and then just add
"scripts": {
"test": "mocha spec"
}
to package.json. That may or may not work in EVERY environment. I know, for instance, with lineman, you have to use bin/mocha. Also, if you don't find a way around this, set your test script up for Unix and then add a second script called "wintest" or something that does whatever you need it to do in Windows. You can name your scripts whatever you want. The default ones (test, start, etc.) can be used with npm [command]; any non-standard ones (like wintest) can be used with npm run-script [command], and they will still work.
A little back story on how/why this works:
When you install a module globally, it's available on PATH (or whatever the windows equivalent is). When you install a project dependency, if that module has any binaries, those are symlinked to node_modules/.bin and when you run npm run [some-command], npm helpfully adds node_modules/.bin to PATH for that command. So when mocha is installed globally "test": "mocha spec" uses your globally installed mocha to run tests. When it's a project dependency, it uses the one in node_modules/.bin. The one gotcha I've found with this is that npm adds node_modules/.bin to the front of PATH, so local binaries will always take precedence over global ones. Almost all of the time, this is what you want, but it's worth knowing that that's how it works (I recently had a bug related to this).
EDIT:
Not sure at what point in npm history this changed, but npm run <script-name> now works (don't need to do npm run-script <script-name> anymore). Possibly run-script still works as well. I'd expect it to, but I haven't tried it.
How can I set package.json up to work on both Windows and Unix?
If you
use Windows
dislike -g global install
...this is a working solution
"scripts": {
"test": "node node_modules/mocha/bin/mocha.js"
},
Notes:
putting node in front shouldn't harm, and can help on Windows (.js extension is not necessarily registered to the nodejus executable, unless you set it so. Could open a text editor, an IDE or (worse) windows scripting host, Internet Explorer…)
Adressing the script directly saves you from needing a global install. (Not judging if this is a good practice)
forward slashes help running under linux (obviously) and do work under windows (in this scenario. Also avoids a windows pitfall: backslashes if used, would need to be doubled – since they are interpreted as escaping the following letter if used solitary).
Don't use global solution, I suggest you follow what the Mocha guys say:
"scripts": {
"test": "node_modules/.bin/mocha -w"
},
Use npm i mocha --save-dev
This will save the module as a development dependency and npm will automatically set up the executables to be used within the scripts object. If you want to use the executables outside of the scripts defined in package.json, you can install it globally as well, although note that you may end up with different versions of the package.
If you only install it globally, other people won't be happy if they try to run your tests (with the standard npm test)
The new way with latest npm versions after 6.x, you needn't install mocha with global mode any more.
"scripts": { "test": "npx mocha" }
npx is installed automatically with new npm installation. It will search
mocha from node_modules/.bin or $PATH
reference: https://www.npmjs.com/package/npx

Resources