├── .gitignore ├── ExternalPackager.js ├── package.json ├── ExternalAsset.js ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Folder view configuration files 2 | .DS_Store 3 | ._* 4 | node_modules 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /ExternalPackager.js: -------------------------------------------------------------------------------- 1 | const { Packager } = require('parcel-bundler'); 2 | 3 | class ExternalPackager extends Packager { 4 | static shouldAddAsset() { 5 | return false; 6 | } 7 | 8 | setup() {} 9 | 10 | async addAsset() {} 11 | 12 | getSize() { 13 | return 0; 14 | } 15 | 16 | end() {} 17 | } 18 | 19 | module.exports = ExternalPackager; 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parcel-plugin-peer-dependencies", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Anton (http://shuvalov.info/)", 6 | "license": "MIT", 7 | "dependencies": { 8 | "read-pkg-up": "^7.0.1" 9 | }, 10 | "devDependencies": { 11 | "parcel-bundler": "^1.12.4", 12 | "resolve-from": "^5.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ExternalAsset.js: -------------------------------------------------------------------------------- 1 | const { Asset } = require("parcel-bundler"); 2 | const { createHash } = require("crypto"); 3 | const resolve = require('resolve-from'); 4 | const path = require('path'); 5 | 6 | function computeMd5(content) { 7 | return createHash("md5") 8 | .update(content || "") 9 | .digest("hex"); 10 | } 11 | 12 | class ExternalAsset extends Asset { 13 | constructor(p, options) { 14 | super(p, options); 15 | const { rootDir } = options; 16 | const name = p 17 | .replace(/^\.\//, '') 18 | .replace(/\.external/, ''); 19 | 20 | const require = path.relative(rootDir, resolve(rootDir, name)); 21 | 22 | this.content = `module.exports=require('${require}')` 23 | } 24 | 25 | load() {} 26 | 27 | generate() { 28 | return { 29 | js: this.content 30 | }; 31 | } 32 | 33 | generateHash() { 34 | return Promise.resolve(computeMd5(this.content)); 35 | } 36 | } 37 | 38 | module.exports = ExternalAsset; 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parcel Plugin Peer Dependencies 2 | 3 | Parcel plugin to exclude peer dependencies. Should be useful with `yarn workspaces`. 4 | 5 | ## Installation 6 | 7 | ``` 8 | yarn add --dev parcel-plugin-peer-dependencies 9 | npm i -D parcel-plugin-peer-dependencies 10 | 11 | ``` 12 | 13 | ## Usage 14 | 15 | Just declare your peerDependencies in the `package.json`: 16 | 17 | ``` 18 | // package.json 19 | { 20 | // ... 21 | "peerDependencies": { 22 | "classnames": "*", 23 | "date-fns": "*", 24 | "lodash.groupby": "*", 25 | "lodash.omit": "*", 26 | "nanoid": "*", 27 | "react": "*", 28 | "swr": "*" 29 | }, 30 | // ... 31 | } 32 | 33 | ``` 34 | 35 | The logic behind is based on idea, that peer dependency is hoisted into the workspace root, 36 | and included into the one of sibling packages. 37 | 38 | 39 | ## Credits 40 | 41 | This plugin was developed, because `parcel-plugin-externals` hadn't worked correct for my workspaces setup, 42 | so I just re-implemented its much simplier version, that supports only peerDependencies, and relays on a 43 | different tools to resolve dependencies paths. Sending virtual thanks to the author. 44 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const readPkg = require('read-pkg-up'); 2 | const resolve = require('resolve-from'); 3 | 4 | const EXTENSION = 'external'; 5 | 6 | module.exports = function(bundler) { 7 | const { rootDir } = bundler.options; 8 | const { packageJson: pkg } = readPkg.sync(rootDir); 9 | const { peerDependencies } = pkg; 10 | if (!peerDependencies) return; 11 | 12 | // Add handlers for external asset types 13 | bundler.addAssetType(EXTENSION, require.resolve("./ExternalAsset")); 14 | bundler.addPackager(EXTENSION, require.resolve("./ExternalPackager")); 15 | 16 | console.log('Peer Dependencies detected:', peerDependencies); 17 | const names = Object.keys(peerDependencies); 18 | const modules = names.reduce((acc, name) => { 19 | // I believe all packages in monorepo should be on the same level 20 | const p = resolve(rootDir, name); 21 | acc[p] = name; 22 | return acc; 23 | }, {}); 24 | 25 | // Monkeypatch asset loader to process external files 26 | const superResolver = bundler.__proto__.getLoadedAsset; 27 | bundler.__proto__.getLoadedAsset = function(p) { 28 | p = modules[p] 29 | ? `./${modules[p]}.${EXTENSION}` 30 | : p; 31 | return superResolver.call(this, p); 32 | }; 33 | }; 34 | --------------------------------------------------------------------------------