Parcel: Parcel keeps rewriting / destroying package.json file

Created on 5 May 2019  路  19Comments  路  Source: parcel-bundler/parcel

馃悰 bug report

In my configuration, parcel rewrite its package.json even though it is told not to ... and since parcel is installed locally (no -g, global is evil) it removes itself from the node module directory, some kind of suicide ...

馃帥 Configuration (.babelrc, package.json, cli command)

package.json:

{
  "name": "MicroCaps",
  "version": "1.0.0",
  "scripts": {
    "watch": "NODE_ENV=development parcel --out-dir=../assets/static/gen --out-file=main.js --public-url=./assets/ main.js",
    "build": "NODE_ENV=production parcel build --out-dir=../assets/static/gen --out-file=main.js --public-url=./assets/ main.js"
  },
  "private": true,
  "dependencies": {
    "babel-preset-env": "^1.7.0",
    "materialize-css": "^1.0.0",
    "node-gyp": "^4.0.0",
    "node-sass": "^4.12.0",
    "parcel-bundler": "^1.12.3",
    "tar": "^4.4.8",
    "uglify-js": "^3.5.10",
    "uglifycss": "0.0.29"
  }
}
babelrc:
```{
  "presets": ["env"]
}

I have very simple main.js

import '../assets/scss/resume.scss'

The config files above are in a directory "parcel"
To reproduce :
```bash

cd parcel
npm install
NODE_ENV=development node_modules/.bin/parcel watch --no-autoinstall --out-dir=../assets/static/gen --out-file=main.js --public-url=./assets/ main.js

After a while the package . json will contain

```json
{
  "devDependencies": {
    "sass": "^1.20.1"
  }
}

and the build fail because parcel will have killed himself by removing itself from node-modules/.bin ...

and this "sass" dependency is wrong because my package.json already contains "node-sass": "^4.12.0"

And parcel does that even though --no-autoinstall is set !!!! (even tough this should not be necessary ...)

馃 Expected Behavior

building the dependencies and NOT touching the package.json file.

馃槸 Current Behavior

Parcel self destuct itself after wrongly changing the package.json file into the aformentionned file..

On the other hand I can clearly see a step "building package.json file" so ... parcel really intend to misbehave ...

(microcaps_site) ~/.../microcaps/parcel >>> NODE_ENV=development node_modules/.bin/parcel watch --no-autoinstall --out-dir=../assets/static/gen --out-file=main.js --public-url=./assets/ main.js           卤[鈼忊棌鈼廬[master]
馃毃  Cannot find module '../builtins/hmr-runtime'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
    at Function.require.resolve (/home/gryom/Projects/microcap_site/MicroCaps/themes/microcaps/parcel/node_modules/v8-compile-cache/v8-compile-cache.js:162:23)
    at JSPackager.end (/home/gryom/Projects/microcap_site/MicroCaps/themes/microcaps/parcel/node_modules/parcel-bundler/src/packagers/JSPackager.js:215:17)
    at Bundle._package (/home/gryom/Projects/microcap_site/MicroCaps/themes/microcaps/parcel/node_modules/parcel-bundler/src/Bundle.js:222:20)

馃拋 Possible Solution

None I can see

馃敠 Context

Tryng to build a theme for the Lektor static cms engine

馃捇 Code Sample

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.3
| Node | 10.13.0
| npm/Yarn |6.9.0
| Operating System | linux manjaro

Bug Confirmed Bug Autoinstall

Most helpful comment

Just bisected what causes this, and I'm importing and using a function from a folder with cross-project code that lies above the package.json scope. I typically do this only for typescript types, to share them between frontend and backend. Apparently parcel breaks when I do this for actual code that is emitted into a bundle. Note that when I only import the function and not use it, this problem does not occur.

All 19 comments

Parcel falls back to sass instead of node-sass if an error occurs while requiring it. See https://github.com/parcel-bundler/parcel/blob/master/packages/core/parcel-bundler/src/assets/SASSAsset.js#L105. So it seems like either node-sass is not installed, or there is some error while requiring it, e.g. it was built for a different node version maybe. You could put a debugger or console log on that line to see the error.

Then it will try to install sass if it is not already installed. 鈥攏o-auto-install only affects code dependencies, things you import or require, not dev dependencies.

Thanks for your answer I will check and rebuild the whole node-module and verify version consistency.
Still for me the main problem is that parcel takes great liberties with the package.json file to the point of destroying it. Why does it do that ?

I'm not sure what's going on there. Parcel certainly doesn't write to package.json, but it does call yarn or npm to install packages, which may write to package.json. Unsure why it would overwrite the whole thing rather than adding the new package... I've never seen that happen before.

Same here, but I'm using yarn+typescript and the only dependency left afterwards is typescript. Weirdly enough the debug log shows npm working, and afterwards a package-lock.json is created. Even though I'm exclusively using yarn and only have a yarn.lock file.

parcel-debug-2019-05-07T09:09:00.390Z.log

Just bisected what causes this, and I'm importing and using a function from a folder with cross-project code that lies above the package.json scope. I typically do this only for typescript types, to share them between frontend and backend. Apparently parcel breaks when I do this for actual code that is emitted into a bundle. Note that when I only import the function and not use it, this problem does not occur.

I've seen my package.json being repeatedly destroyed too (overwritten by an empty one with just a single dependency in it). This happened when importing out-of-project JS files using ../../.. (as I thought was the recommended way for mono-repos).

My workaround is to use npm-level package links (npm i ../package) so the import statements do not have ../../.. paths. (However, this triggers bug #1838)

I'm also experiencing this kind of Parcel's suicide... The package.json is completely wrecked after running it. One day it works, the next it is broken to an unusable degree. Extremely annoying.

BTW @devongovett, there is no such option as --no-auto-install.

My case seems to be the same as @Wassasin's (good catch!), that is, the problem starts occurring once I import a file from a folder holding code common to server and client. Are we supposed to do something special to achieve this? (Regardless, the outcome of this setup should not be a complete destruction of your dependencies.)

@inad9300 it's --no-autoinstall: https://parceljs.org/cli.html#disable-autoinstall

@mischnic I know.

Any progress on this front? Destroying people's files at random seems quite a priority to me.

I'm lucky to be using version control, which allows me to "only" lose my local changes, but I cannot imagine someone who hasn't set up one yet losing absolutely everything, or someone having made extensive changes such as preparing some scripts.

The first issue here is that Parcel's localRequire is passed the asset path to search for the module (e.g. node-sass), but with ../style.scss, the node_modules of your current package is never searched.
The way the package root to install the new package is derived seems strange to me (this is root cause of this issue, this resolving doesn't work with ../ paths):

  let packageLocation = await config.resolve(filepath, ['package.json']);
  let cwd = packageLocation ? path.dirname(packageLocation) : process.cwd();

Furthermore, the npm/yarn detection doesn't work.

packageManager = await determinePackageManager(cwd);

And finally, here the package.json is cleared:

  // npm doesn't auto-create a package.json when installing,
  // so create an empty one if needed.
  if (packageManager === 'npm' && !packageLocation) {
    await fs.writeFile(path.join(cwd, 'package.json'), '{}');
  }

https://github.com/parcel-bundler/parcel/blob/7ad25fd0958cb39c8595a0d667e9bc0f4c0250f4/packages/core/parcel-bundler/src/utils/installPackage.js#L22-L42

--no-autoinstall should definitely disable all messing with package.json. I just wasted a bunch of time figuring out that it doesn't! :O For a build tool to mess with my package.json without consulting me is madness, IMHO.

--no-autoinstall doesn't seem to stop the destruction of package.json.
How can i possibly import files from outside the project?

similar to @bertfreudenberg, when I refactored some API code from the UI, creating a common folder, and then importing from ../../../ I get erratic behavior with parcel

For me, it was very odd typescript behavior (Array.entries() was not working??) No browser error reported. Some stuff was working, parcel reported no error.

tried to resolve by moving the UI folder outside of my larger "project" folder to isolate, and that's when my package.json started getting deleted.

I fixed it in my setup by just symlinking the ../../../ to the UI folder as one would typically expect, but this was a very odd bug, hopefully this helps others.

My situation is similar to the ones described above:

  • Typescript
  • Files outside of directory other than root
  • Files being imported with relative paths (import x from '../../..')

When running parcel my package.json first goes empty ({}) and then results in a file only containing a single dev-dependency (typescript).
Managed to temporarily fix it by using a symlink, however would definitely prefer a solution without.

Is there any news to this bug?

Related to this, to avoid any modification, could the autoinstall instead of yarn install be yarn install --frozen-lockfile?

This is an absurd bug - on my system running watch seems to send it into some sort of building-death-spiral.

gonna close this as this no longer really happens in Parcel 2, also opened up a PR to make the autoinstall behaviour even less extreme

Was this page helpful?
0 / 5 - 0 ratings