parcel-bundler / parcel

The zero configuration build tool for the web. 📦🚀
https://parceljs.org
MIT License
43.41k stars 2.26k forks source link

Plugin development is a bit difficult locally #590

Closed jtenner closed 6 years ago

jtenner commented 6 years ago

Choose one: is this a 🐛 bug report or 🙋 feature request?

🙋 Support npm linked plugins!

🎛 Configuration (.babelrc, package.json, cli command)

The configuration isn't important here, but because I can't link a plugin, I can't test to see if it works before submitting my package to npm.

🤔 Expected Behavior

Well, by the description of the problem, it should be supported, I would think!

😯 Current Behavior

It currently does not support linked plugins.

💁 Possible Solution

I haven't enough information on how npm link works, but it would be great to learn, since I'm trying to design something similar in nature to parcel (not a js packager).

🔦 Context

I am trying to accomplish creating a plugin locally so that I can start to help parcel support different sorts of file types.

💻 Code Sample

This is not necessary.

🌍 Your Environment

Windows 10, latest node, latest npm. I do not use yarn personally.

elsassph commented 6 years ago

I had the same problem - there are different ways to handle that (they could be documented on Parcel website):

  1. Using npm link

Now you can edit your plugin sources.

elsassph commented 6 years ago
  1. Alternative option that I'm using because I'm hacking Parceljs:

In your sandbox project, create 2 scripts to manually call Parceljs with your plugin:

// start.js
const Bundler = require('parcel-bundler');

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

// you may be messing quite a bit in a new plugin so you may want to add error capture
process.on('unhandledRejection', (reason, p) => {
    console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

// manually set up the bundler
const bundler = new Bundler('./index.html');

bundler.addPackager('ext', require.resolve('./MyPackager'));
bundler.addAssetType('ext', require.resolve('./MyAsset'));

bundler.serve(1234, false);
// build.js
const Bundler = require('parcel-bundler');

process.env.NODE_ENV = 'production';

// you may be messing quite a bit in a new plugin so you may want to add error capture
process.on('unhandledRejection', (reason, p) => {
    console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

// manually set up the bundler
const bundler = new Bundler('./index.html');

bundler.addPackager('ext', require.resolve('./MyPackager'));
bundler.addAssetType('ext', require.resolve('./MyAsset'));

bundler.bundle();

Run as node start.js / node build.js.

I've added these scripts to my package.json:

  "scripts": {
    "clean": "rm -rf .cache && rm -rf dist",
    "start": "node script/start.js",
    "build": "node script/build.js"
  },

PS: I'm on Windows but I have bash commands in my PATH (it's an option when you install msysgit ).

PPS: never run yarn clean - always yarn run clean

jtenner commented 6 years ago

I really like this idea.

I tweaked the resulting idea by simply doing this:

const Bundler = require('parcel-bundler');
const pkg = require("./package.json");
process.env.NODE_ENV = 'production';

// you may be messing quite a bit in a new plugin so you may want to add error capture
process.on('unhandledRejection', (reason, p) => {
    console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

// manually set up the bundler
const bundler = new Bundler(`./${pkg.main}`);

//require the plugin and hook everything up the way the plugin works
require('parcel-plugin-spritesheet')(bundler);

bundler.bundle();
jtenner commented 6 years ago

I had to manually link parcel-bundler in the project, but it appears that I get another sort of problem if I do this. I'll take a look deeper.

elsassph commented 6 years ago

Well the whole point of the scripts is to be able to work without creating the npm plugin at all :) I can hack a plugin directly from my test project and then I'll promote it to a plugin.

And yes I guess you should npm/yarn install parcel-bundler in the project.

jtenner commented 6 years ago

I used npm link on a local version of parcel-bundler it worked nicely. Closing because I managed to figure out how to test it without it being a dependency of the project. I still think npm link plugin should work though.

mischnic commented 6 years ago

Parcel gets the list of dependencies in package.json and loads listed plugins. Therefore plugins linked to node_modules (but not listed in package.json) won't get loaded. My workaround is: linking the plugin into node_modules and then manually adding it to the package file:

"dependencies":{
  "parcel-plugin-emscripten": "something"
}

(Just be sure not to run yarn without removing this line, because technically it's not a valid version.)

mischnic commented 6 years ago

What about specifying a plugin, which is linked inside node_modules, as cli argument?

I.e. running parcel --plugin myplugin src/index.html to load parcel-plugin-myplugin as well.

dobesv commented 6 years ago

Have you tried making a test project and doing yarn install file:path/to/parcel-plugin-bla. Should install the plugin into node_modules as a copy of your plugin without publishing it. Have you re-run yarn to update that copy on each change, but I suppose it's better than re-publishing on each change.

DeMoorJasper commented 6 years ago

Has this been resolved?

dobesv commented 6 years ago

It seems like @jtenner would have to say for sure, but there have been solutions presented such as using npm link or installing using file:.

elsassph commented 6 years ago

I think a proper answer should be to have a wiki page describing the dev process options as evoked here.

jtenner commented 6 years ago

I didn't mean to hold this open. Installing the package from the github repo was enough to fix the issue.

ozanmuyes commented 5 years ago

As @elsassph pointed out using npm link solves the issue. But I think it's worth to mention the issue is not Parcel related.


Although npm link page describes what it is and gives an example how to use it, here is the process in a nutshell;

  1. Create your local plugin directory i.e. mkdir parcel-plugin-yourplugin && cd parcel-plugin-yourplugin && npm init -y and then write the plugin
  2. Run npm link command on the plugin directory first This creates global link on your development environment, so you don't have to push your plugin to npm
  3. Navigate to your test project directory (which depends/dev-depends on parcel-bundler)
  4. Run npm link parcel-plugin-yourplugin Please note the plugin name, you have to write it this time as if you were downloading it from npm

After those steps any (file) change on 'parcel-plugin-yourplugin' directory will be reflected on you test projects 'node_modules' directory, this is simply because your plugin directory in the test project's 'node_modules' is a symbolic link.


Edit 1: Symbolic links are supported bu *nix systems, just noticed @jtenner's OS is Windows. So npm link might not work but the idea is the same; your plugin should be available globally (like in npm -g) and test project's 'node_modules' directory should have a subdirectory for that "global" installment. So you might want to check out the mklink command on Windows.

Edit 2: On the test project (after successfully depend on your plugin) any time you use npm install you have to re-do the 3rd and 4th steps.

SalvatorePreviti commented 4 years ago

i wrote this supersimple package that seems to solve the problem for my case - https://github.com/SalvatorePreviti/parcel-plugin-local-plugins - the only limitation of course is that if you change the plugin source code you need to restart parcel. Just define in package.json which files needs to be loaded as plugins and you are ready to go, monorepos included