meteor-svelte / meteor-svelte

Build cybernetically enhanced web apps with Meteor and Svelte.
MIT License
114 stars 13 forks source link

Require manual install of svelte with npm #11

Open zimme opened 7 years ago

zimme commented 7 years ago

I was laying on the beach today and for some reason I started to think about this package and started thinking that maybe we should require the users to install svelte manually and we just provide the meteor compiler.

meteor add svelte:compiler
meteor npm i -D svelte

Then we just check that svelte is available when the compiler runs and print an error message if not. This way we won't be required to always keep this package up to date with the latest svelte version.

klaussner commented 7 years ago

I think peer dependencies only work on the application level. To import a package in a build plugin, it has to be listed in Npm.depends. 🙁

klaussner commented 7 years ago

I've opened a feature request for this: https://github.com/meteor/meteor-feature-requests/issues/164

arggh commented 5 years ago

...in the meanwhile, maybe it's a good idea to point this out in the documentation: especially that the version of Svelte installed as app's dependency has to match the version used by the compiler, which is set in stone.

(This is the reason why I immediately forked this package and run a locally modified version, so I can keep using the latest Svelte and match the versions between app / compiler)

klaussner commented 5 years ago

Good idea! I've added a note about the npm package version to the README.

CaptainN commented 5 years ago

You can use findUp to find the project root, and then use require to get the package from the project:

import { readFileSync } from 'fs';
import findUp from 'find-up';

let options;
const pkgPath = findUp.sync('package.json');
const root = pkgPath.substring(0, pkgPath.length - 12);

import htmlparser from 'htmlparser2';
import sourcemap from 'source-map';
const svelte = require(root + 'node_modules/svelte/compiler');

I'm happy to write a PR. I could even have it check for a user installed version defined in package.json, and warn the user if none is installed. Or have it default to the internal version if there are any problems loading the user copy.

CaptainN commented 5 years ago

Here's an even better version

import { readFileSync } from 'fs';
import findUp from 'find-up';

// Read package information from user's `package.json`
const pkgPath = findUp.sync('package.json');
const pkg = pkgPath ? JSON.parse(readFileSync(pkgPath, 'utf8')) : {};
const packages = Object.assign({}, pkg.dependencies, pkg.devDependencies);
const root = pkgPath.substring(0, pkgPath.length - 12);

// prefer the user installed/managed version
function req (name) {
  let mod;
  if (pkgPath && packages[name]) {
    try {
      mod = require(root + 'node_modules/' + name);
    } catch (e) {
      console.warn('Meteor Svelte: ' + name + ' is defined in package.json, but could not be loaded. Did you run `meteor npm install`?');
      console.log('Meteor Svelte: Falling back to embedded version of ' + name);
      mod = require(name);
    }
  } else {
    mod = require(name);
  }
  return mod;
}

// Load the user installed/managed versions of these packages
// :TODO: Do some helpful version checking on the optional user modules - htmlparser 4.0 does not work for example
const htmlparser = req('htmlparser2');
const sourcemap = req('source-map');
const svelte = req('svelte/compiler');