yarnpkg / berry

📦🐈 Active development trunk for Yarn ⚒
https://yarnpkg.com
BSD 2-Clause "Simplified" License
7.45k stars 1.11k forks source link

[Feature] Add `--mode=skip-build` to `yarn workspaces focus --production` #3524

Open ai opened 3 years ago

ai commented 3 years ago

Describe the user story

I have Docker image with my Node.js app. For performance and security reasons, I need:

  1. Install only dependencies, not devDependnecies.
  2. Do not run scripts like install

I found that I can use yarn workspaces focus --production to install production dependencies, but yarn workspaces focus have no support for --mode=skip-build.

Describe the solution you'd like

yarn workspaces focus --production --mode=skip-build

Describe the drawbacks of your solution

Do not see from my area of expertise.

Describe alternatives you've considered

My current solution is:

RUN yarn plugin import workspace-tools
RUN yarn install --mode=skip-build --immutable
RUN yarn workspaces focus --production

But it is slow.

sod commented 3 years ago

Seeing the RUN, are you talking about docker? You could use buildkit, which caches each step. If copied files didn't change, it skips the following commands.

You only copy all package.json and yarn related files and do your 3 commands. Then docker will skip the entire install if your dependencies didn't change.

Only after yarn install you copy the rest (so a change to the source code doesn't invalidate the install cache)

look vaguely like:

# copy yarn files
COPY ./yarn.lock /build/
COPY ./.yarnrc.yml /build/
COPY ./.yarn/releases/* /build/.yarn/releases/

# copy all package.jsons
COPY ./package.json /build/
COPY ./foo/package.json /build/foo/
COPY ./bar/package.json /build/bar/

# single monorepo yarn install
RUN yarn plugin import workspace-tools
RUN yarn install --mode=skip-build --immutable
RUN yarn workspaces focus --production

# copy the rest
COPY ./foo /build/foo
COPY ./bar /build/bar

Then docker will cache the entire install for you.

ai commented 3 years ago

You could use buildkit, which caches each step.

Thanks. Yeap, we have this order to cache steps.

You only copy all package.json and yarn related files and do your 3 commands. Then docker will skip the entire install if your dependencies didn't change.

The problem is on package.json changes. Previously yarn install --production --skip-scripts was faster because it do not download a huge amound of development dependencies.

RUN yarn workspaces focus --production

Just a quick question. Am I right, that yarn workspaces focus --production will just clean dependencies without re-calling any scripts like postinstall or postuninstall?

merceyz commented 3 years ago

Just a quick question. Am I right, that yarn workspaces focus --production will just clean dependencies without re-calling any scripts like postinstall or postuninstall?

It installs your project in the same way as yarn install does, the difference is that it just "pretends" that unrelated workspaces and devDependencies doesn't exist. https://yarnpkg.com/advanced/error-codes/#yn0008---must_rebuild explains what causes it to re-run postinstall scripts (postuninstall isn't a thing)

ai commented 3 years ago

explains what causes it to re-run postinstall scripts

Oh 😰 Can we add skip-build to yarn workspaces focus?

belgattitude commented 3 years ago

BTW, I've faced this issue too.

@ai a partial workaround (using buildkit) that I use is to set a env to skip postinstall for local packages.

i.e:

RUN --mount=type=cache,target=/root/.yarn-cache \
    SKIP_POSTINSTALL=1 \
    YARN_CACHE_FOLDER=/root/.yarn-cache \
    yarn workspaces focus web-app --production

In my app package.json

{
  "name": "web-app",
  "scripts": {
    "postinstall": "test -n \"$SKIP_POSTINSTALL\" || yarn workspace @your-org/db-main-prisma run prisma generate"
  }
}

It as some limitations though.

  1. test -n would not work on windows (I guess some cross-platform tools exists)
  2. it does not prevent postinstall to be run on external deps... New kid on the block tend to download native binaries (ie: nextjs with swc compiler, sharp, prisma, @sentry/cli....) on postinstall, but when they have to be build (node-gyp) it might cause a full rebuild in the link step (even if they were built in a previous yarn install). Like @merceyz mentionned above.
Example of link step ``` $ yarn install /// ... $ yarn workspace @your-org/db-main-prisma run prisma /// .... ➤ YN0000: ┌ Link step ➤ YN0062: │ @next/swc-darwin-arm64@npm:11.1.2 The platform linux is incompatible with this module, link skipped. ➤ YN0062: │ @next/swc-darwin-x64@npm:11.1.2 The platform linux is incompatible with this module, link skipped. ➤ YN0062: │ @next/swc-win32-x64-msvc@npm:11.1.2 The platform linux is incompatible with this module, link skipped. ➤ YN0062: │ fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7 The platform linux is incompatible with this module, link skipped. ➤ YN0008: │ sharp@npm:0.29.1 must be rebuilt because its dependency tree changed ➤ YN0008: │ @prisma/client@npm:3.2.1 [11082] must be rebuilt because its dependency tree changed ➤ YN0008: │ @sentry/cli@npm:1.68.0 must be rebuilt because its dependency tree changed ➤ YN0008: │ web-app@workspace:apps/web-app must be rebuilt because its dependency tree changed ➤ YN0009: │ web-app@workspace:apps/web-app couldn't be built successfully (exit code 1, logs can be found here: /tmp/xfs-b749db10/build.log) ➤ YN0000: └ Completed in 3s 178ms ```

But IMO, --mode=skip-build (or better name) would be welcome.

PS: you can find the idea here - it's not working right now :)

zyf0330 commented 1 year ago

@ai Hello, I know that yarn has a config option enableScripts which disables postinstall script. And yarn is different with npm, yarn doesn't execute scripts except postinstall inside the install step.

akwodkiewicz commented 2 months ago

Is the development on the existing PR going to be continued, or should we close that one and prepare a new one?