New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider installing devDependencies by default #431
Comments
For users that don't commit build assets to their source directory (building dynamically is the better approach IMO), I see the building assets step as a production dependency, not a development dependency - which makes putting them in An alternative to ease onboarding might be for the buildpack to check (on a non-zero return from the preinstall/postinstall/heroku-* |
@edmorley I don't necessarily disagree, but there is a big difference between what users should do, and what the actually do in practice. Checking in built assets has its own issues, and goes against established community best practices. We should meet people where they are when we can. If a warning doesn't already exists I'm definitely for adding that, but I'd prefer for things to "just work" rather than make a non-trivial percentage of users either modify their app or set an environment variable to run on Heroku. |
Reading back I can see it was ambiguous -- by "the better approach" I meant I prefer not committing assets. I don't for one minute think suggesting people change their workflow in that regard is practical :-) |
Oh, I see now. I don't think forcing people to put things under The larger story is that frontend build errors are a huge % of the number of support tickets that we receive for Node, and anything we can do to make that process easier is a high priority for me. |
The right solution would be to not have to rely on the user to move to devDependencies to Why not just search for a new flag in the |
npm-pack seems to fit the bill here. npm-pack runs the (This also gives you flexibility as to whether node_modules are included in the slug itself, since the npm-packed tarball is no longer reliant on them for building, you could get away with not including them in the slug and simply This is pretty close to the workflow I see and advocate in most CI pipelines, anyhow. (npm install with devDeps on a build box, then npm-pack, then saving/moving/deploying the packed tarball to prod box, unzip, This makes an app's package.json scripts/deps congruent with the scripts/deps for modules, and follows npm's conventions more closely. It also makes sense semantically (npm-publish a module which calls npm-pack internally; and npm-pack an app for deployment) |
@jasonkarns There are a couple of issues that I see there:
but mainly we have 10's of thousands of existing apps using the current deploy process. |
I don't understand why this wouldn't work. My intention is that all of the above would happen in the build pack and not have any impact on users (migration path may be necessary for some configurations, i'm unsure). |
A better explanation: after the buildpack does the git checkout of master, runs A couple notes probably going unmentioned here:
Hopefully that clarifies my suggestion. |
From the
For this reason, I disagree with the devDependencies section of Heroku Node.js Support. To follow npm's recommendations and avoid confusion, I think it would be better to either set |
The way I see |
I agree, as long as you can treat libraries only used on the client side as build time dependencies because a bundler is inlining them for you. |
If this is quick even for large dependency trees then it sounds like a great solution 👍 |
That sounds good, the |
Instead of doing the whole install, pack, reinstall workflow. Maybe it should just run |
@bbatha at what point? without a non-production install, what would be getting pruned? how would the app get built? (ie, the babel compilation, etc) this is done automatically by npm-pack via the |
Also, I could be wrong but I think |
Nope. Neither |
Well, I should clarify. It sets An example package with a postinstall script:
|
This is just an alternative to using |
@jasonkarns I agree that it doesn't affect runtime directly, but if a build tool behaves differently in production (webpack often does depending on its configuration), the code and dependencies may be different at runtime in ways that affect performance, security, stability, etc. |
running npm install twice doesn't actually install anything twice. It builds the virtual dep tree in memory and then ensures that the filesystem matches it. Running npm-prune is functionally equivalent. So I was thrown off by the comment that "prune" could replace "install, pack, reinstall".
The first install (with devDeps) is obviously still necessary such that devDeps exist in order to build the app. The pack step is necessary to compile the app while devDeps are available. So, a more accurate interpretation of that comment is that "prune" just replaces the last "reinstall". Which I'll concede.
edit - prune will result in a slightly different node_modules tree because it doesn't re-flatten any duplicated deps. So I'm maintaining my hesitation for using prune in favor of running install a second time (which doesn't run any slower). Though practically, they should still be the same. I just trust npm-install a bit more. |
Sorry if that's unclear. What I meant is that install, pack and then prune can be just install then prune. There's no need for the pack step unless your going to upload the built package somewhere else to npm or from CI system as a built slug. |
To clarify, those two sets of commands are only the same if your build tools executed in |
@bbatha heroku would need to run the compilation step, regardless. having heroku specify some custom-to-heroku npm script as the build step is inferior to using the conventional (and established norm) of using @nickmccurdy There shouldn't be any build tools being executed during npm-install. The only things running during npm-install are |
That's cool, I didn't know I was implying that |
@nickmccurdy Ah! Okay! Now I get you. 👍 thanks for being patient while I caught up :) So yeah, in that case, I suppose the
EDIT:
|
@jasonkarns it is not uncommon for build tools to alter behavior based on |
Most of the logic here is sound for running pack. 👍 for reusing existing specification mechanisms. However, I don't really see how If your someone who builds on CI and uploads the slug to heroku. The third thing running pack in the directory doesn't really account for is the multi-buildpack case where you may also want to include other directories in the slug that aren't listed in your |
Yeah, my original suggestion would have resulted in two tarballs that the buildpack would need to handle: the npm-packed tarball, and the node_modules directory itself. Not as clean as just having a single tarball, but I was thinking that two would be easily managed. Re: multi-buildpacks. I wasn't even thinking about those. Good call. |
That's unfortunate, should we avoid pack then or is there a way to get it to work with multiple buildpacks? |
Is there any suggestion as a result of this topic?
|
@Ajaxy (quick random tidbit: |
@Ajaxy I'm afraid other work has taken priority, but I'll be working on a PR next week that will make that the default In the mean time you could run |
Thanks, so I ended up with: {
"build": "babel src -d build",
"deploy:staging": "git push heroku master -f",
"deploy:production": "heroku pipelines:promote",
"prepare": "npm run build",
"heroku-postbuild": "npm prune --production"
} |
Also, it seems that if I add |
It hasn't worked for me.
So seems dev packages are not installed.
|
Well, it seems the last one was some unrelated issue. Now it's gone. Also, for those using
instead of
|
@jmorrell I just noticed that setting Figured I'd mention it for consideration when you work on #519 |
@lirbank I think in that case you can check the value of the
In #519 I'll be sure to do the reasonable thing in |
Quick update, for anyone interested, here is my final solution that works with Heroku CI too:
|
Fixes #431 Many users getting started with Heroku try to run a build step with webpack, gulp, etc only to find that it's in their devDependencies and not installed by default on Heroku. They then have to figure out how to tell Heroku to install these. Defaulting to installing everything makes for a smoother onboarding. Changes the default behavior to install `devDependencies`, run the build step, and then prune the `devDependencies` once the build step is complete.
Pro: Many users getting started with Heroku try to run a build step with
webpack
,gulp
, etc only to find that it's in theirdevDependencies
and not installed by default on Heroku. They then have to figure out how to tell Heroku to install these. Defaulting to installing everything makes for a smoother onboarding.Con: Longer install times and larger slugs for existing large apps
First step: gather metrics
The text was updated successfully, but these errors were encountered: