简体   繁体   中英

Meteor package import css files from npm package that is only marked as dependency using tmeasday:check-npm-versions

Since quite some time there is this package tmeasday:check-npm-versions that allows to define an implicit npm package dependency to a Meteor package.

Use this package if you are writing an Atmosphere package that depends on a given npm package is installed at the app level of projects you are installed in.

Now I am writing a Meteor package, say me:my-package and have a dependency to an npm package, say some-package . This npm package requires me to import these styles manually.

The folder for that is located at some-package/style/main.less .

I tried to import the file within the package but it can't be imported into my package's less file:

@import "some-package/style/main";
@import "{}/some-package/style/main";
@import "node_modules/some-package/style/main";
@import "{}/node_modules/some-package/style/main";

all throw the same error:

While processing files with less (for target web.browser):
packages/me:my-package/style.less:1: Unknown import: <one of the path's above>

The obvious reason here: a Meteor package usually requires me to add files via api.addFiles but the package has no 'real dependency' to the npm package to import this file.

I could move the 'responsibility' of importing the styles to the application that will use 'me:my-package' because it will have to install the npm package, too.

Putting the following line into the css of the application that will use me:my-package actually works:

@import "/node_modules/some-package/style/main.less";

But this would also force the app to install less or sass if the package uses it (as less in my case).

Somebody managed to solve this in a package-user-friendly way?

After some time I came back to this issue and found an answer just by accident. It can be achieved with the dynamic-import package.

You need to add all the styles to import in an exported function that returns an array of dynamic imports.

So let's consider the hypothetical package me:mypackage :

Package.describe({
  name: 'me:mypackage',
  // ...
});

// this example uses it only on the client 
// because the focus is importing styles
// but the pattern could work for other assets, too
Package.onUse(function(api) {
  api.versionsFrom('1.6');
  api.use('ecmascript', 'client');
  api.use('underscore', 'client');
  api.use('tmeasday:check-npm-versions', 'client')
  api.mainModule('mypackage.js', 'client');
});

Note, that I use api.mainModule here, so we will export something. If you want to add the package to the global namespace you will have to attach the function with the dynamic imports somewhere to make it accessible.

In your main module you declare your npm dependencies and your dynamic styles import:

import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
checkNpmVersions({
  'some-package': '4.x.x'
}, 'me:mypackage');

const somepackage = require('some-package)
// do whatever with some-package....

// export a function that let's your project
// to be able to just import the right style deps
export const importStyles = function() {
  return [
    import('some-package/style/main.css'),
    // ... and more if required
  ]
}

In you project you need to add dynamic-imports and me:mypackage :

$ meteor add dynamic-imports me:mypackage

and import it on top-level in your client/main.js :

import { importStyles } from 'meteor/me:mypackage'
importStyles()

Advantage:

  • No need to explicitly import styles in your main project
  • You can continue to avoid NPM.depends in your package
  • Just update the package if the dependent npm package changes it's structure, paths etc.
  • Dynamic imports return promises so you can "wait" until all dependencies are loaded

Disadvantage:

  • Assets are not available immediately, there may be a slight offset between loading and displaying. Sometimes you see the styles not being set for some miliseconds and you may show a loading screen / splash screen until all styles are imported

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM