Stencil: Assets bundling is broken for 'dist' target

Created on 2 Apr 2020  ·  6Comments  ·  Source: ionic-team/stencil

Stencil version:

 @stencil/[email protected]

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

Build fails:

[36:30.8]  @stencil/core v1.12.0
[36:34.1]  build, role-management-app, prod mode, started ...
[36:34.2]  transpile started ...
[36:41.6]  transpile finished in 7.40 s
[36:41.6]  copy started ...
[36:41.6]  generate lazy started ...
[36:42.0]  copy finished (2 files) in 409 ms
[36:55.4]  generate lazy finished in 13.81 s

[ ERROR ]  EBUSY: resource busy or locked, copyfile
           'PATH_TO_COMPONENT\assets\calendar.svg'
           ->
           'dist\collection\app\PATH_TO_COMPONENT\assets\calendar.svg'

[36:55.5]  build failed in 21.35 s

Expected behavior:

Build succeeds.

Steps to reproduce:

  1. Create a component with a single linked asset (via assetsDir)
  2. Configure Stencil to use dist target:
  outputTargets: [
    {
      type: 'dist'
    }
  ]
  1. Build in prod mode: stencil build

Other information:

My observations:

  1. For some reason, build tries to copy 2 files, despite having only one asset file
  2. After removing assetsDirs, assets folder is still copied for www target (and dist)
triage

All 6 comments

This also happens with files in src/assets. Here's a minimal test case:

npm init stencil

> component
> test-project

cd test-project
npm install @stencil/[email protected]

mkdir src/assets
echo "test" > src/assets/test.txt

npm start

Result:

[ ERROR ] ENOENT: no such file or directory, copyfile '/Users/me/Projects/test-project/src/assets/test.txt' ->
'/Users/me/Projects/test-project/www/assets/test.txt'

[46:35.9] build failed, watching for changes... in 1.27 s

Affected versions:

  • 1.12.1 ❌
  • 1.11.3 ❌
  • 1.10.3 ❌
  • 1.10.2 ❌
  • 1.10.1 ❌
  • 1.10.0 ❌ <-- introduced
  • 1.9.2 ✅
  • 1.8.8 ✅

Notes:

It seems like the copy task is running before the dist and www folders exist.

If you run the build at least once _before_ adding any assets, the dist and www folders will be created and the error won't occur. However, removing the folders will cause the error to resurface.

This now happens for the www folder as well 😩
introduced at 1.12.3

After upgraded NodeJS from v10.19.0 to v10.20.1, build process was back to normal.

I stumbled across this again today and upgraded from Node 10.11 to 12.18 and the build is now successful. 🤷🏻‍♂️

I'm having this issue as well, and I'm on Node 12.19 with Stencil 2.3.0

I can temporarily resolve the issue by introducing nonsense files: lala.txt or copy of the README.md file. Any file will do. I can use this for anywhere between 1 tot 50 restarts, but once I have the EBUSY again I need to introduce another change. So then I introduce another file, or when I'm already at two dummy files I delete either.

This is annoying for a local development environment, but adding the files to gitignore won't work for CI/CD :(

Alright so I did some research and it appears to be an async problem.

I traced the issue back to the node specific sys implementation for copying files, specifically here: https://github.com/ionic-team/stencil/blob/master/src/sys/node/node-copy-tasks.ts#L37

await Promise.all(tasks.map(copyTask => copyFile(copyTask.src, copyTask.dest)));

The tasks.map() output passed to Promise.all() creates parallel running copyFile() tasks. The tasks array contains references to the same file (for me: components/icon/icon-assets/icons.svg) twice. It tries to copy the same file at the same time.

I was unable to get a local stencil environment running for my component library because I'm making use of Yarn Workspaces and somehow the yarn link would not work. So I want all out and ploughed through the minified files:

`node_modules\@stencil\coresys\node\index.js line 95 and 96:

const e = s.splice(0, 100);
await Promise.all(e.map((e => copyFile(e.src, e.dest))));

I replaced that with

    for (const e of s.splice(0, 100)) {
     await copyFile(e.src, e.dest);
   }

So now I'm copying the files one by one.

It appears to be working, but I'll get back to you. I persisted this change in my project using patch-package so I can try this in my CI/CD as well. If I don't see any issues in a week, I'll create a PR with a change in the original file.

I don't use deno, I dont know if this is a problem there as well.

Edit: After some thoughts there should be a better solution. Bigger projects benefit from the async copy method. Maybe some kind of grouping logic where the same files are copied after one another but unique files are running in parallel

Was this page helpful?
0 / 5 - 0 ratings

Related issues

joewoodhouse picture joewoodhouse  ·  3Comments

bekliev picture bekliev  ·  3Comments

ryanmunger picture ryanmunger  ·  3Comments

anthonylebrun picture anthonylebrun  ·  3Comments

cjorasch picture cjorasch  ·  3Comments