Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.3] Style files imports from node_modules #6037

Closed
juliancwirko opened this issue Jan 19, 2016 · 117 comments
Closed

[1.3] Style files imports from node_modules #6037

juliancwirko opened this issue Jan 19, 2016 · 117 comments
Assignees
Milestone

Comments

@juliancwirko
Copy link
Contributor

How to import .scss files located in the installed npm package (in node_modules). For example I do:

npm install foundation-sites --save

And now I want to import .scss files from node_modules/foundation-sites
I mean something like (in main.scss in the app):

@import 'foundation-sites/scss/foundation.scss';

I've tried many combinations, like {}/node_modules/foundation-sites... , {}/foundation-sites..., /node_modules/foundation-sites..., etc.

Nothing works with fourseven:scss.

Do we have a solution for this in Meteor 1.3? I gues that node_modules is ignored so .scss compiler doesn't see the files. I think this is the use case when compiler should see node_modules folder.

@benjamn
Copy link
Contributor

benjamn commented Jan 20, 2016

This is definitely an interesting feature to consider. Right now this won't work because only .js and .json files can be imported from node_modules directories. Additionally, we don't run compiler plugins on files in node_modules directories (related: #5892). Finally, .scss files don't use the JS module system currently, though perhaps fourseven:scss could be updated to generate CommonJS instead of CSS resources.

I'm going to leave this issue open but remove it from the Meteor 1.3 milestone for now, because I'm doubtful we will have a solution for this by the time we release 1.3 (but perhaps as soon as ~1.3.1).

@juliancwirko
Copy link
Contributor Author

Ok, thanks.
@sebakerckhof and @fourseven may also be interested in it.

@sebakerckhof
Copy link
Contributor

Okay, some context: Currently Meteor feeds entry-point (=non-imports) .scss files into our compile plugin (fourseven:scss). Most of the code of our plugin is about handling imports (with respect to cross-package imports etc.). Some limitations of node-sass/libsass make this a bit harder than for stylus/less.

If I understand correctly (warning: I haven't looked into meteor 1.3) 2 things should change:

  1. We should be able to generate commonjs files. I know CSS and I know CommonJS, but I have absolutely no idea what these have in common and how I should generate commonjs files from scss.

  2. Meteor should feed us with scss files from node_modules directory. But how does this play together with the current cross-package import syntax (= {packagename}/file.scss)? In this case, what does {packagename} refer to?

@juliancwirko
Copy link
Contributor Author

I don't know exactly how it works internally, but I think we need to treat node_modules (it is in app root dir) as a normal directory when importing in .scss file. I don't know if we need imports in CommonJS-sense. I mean scss imports only (at least for now). And {package:name}/myfiles.scss could still work the same way.

So if now I can do @import 'my-other.scss' (from the same folder) then I should also do @import /node_modules/package-name/other.scss or maybe @import {}/node_modules/package-name/other.scss or even better just @import 'the-name-of-npm-module-installed-in-node_modules/other.scss' and it seems like scss builder doesn't see node_modules

This is how I understand it, but I don't know exactly how Meteor treats node_modules dir in v1.3 and how fourseven:scss works.

@thatgibbyguy
Copy link

I've been able to come to somewhat of a solution using fourseven/meteor-scss. In the root of your app you should have a file scss.json where you include the path to your package(s):

{
  "includePaths": [
    "node_modules"
  ]
}

Then you can import them in your scss file by @import "foundation-sites/scss/foundation.scss";

@juliancwirko
Copy link
Contributor Author

@thatgibbyguy cool! It should be enought for now, but I think that imports from node_modules should be allowed by default in Meteor ;) anyway, thanks for that info.

@benjamn
Copy link
Contributor

benjamn commented Feb 4, 2016

One of the reasons I was hesitant to include anything other than .js and .json files in node_modules directories was that node_modules directory trees can be really large, and I was worried about build times getting much longer.

It occurs to me that there is a middle ground: we could allow any files in direct node_modules/* dependencies to be imported, but ignore files in nested (indirect) dependencies (node_modules/*/node_modules/*).

If we do that, then if you want to import a non-JS file from a package in node_modules, you just have to make sure it is installed as a direct dependency, which seems pretty reasonable to me.

@benjamn benjamn added the desired label Feb 4, 2016
@thatgibbyguy
Copy link

@benjamn Yeah, an alternative would be like this:

{
  "includePaths": [
    "node_modules/foundation-sites/scss"
  ]
}

@import "foundation.scss";

@juliancwirko
Copy link
Contributor Author

@benjamn yeah, it would be great. Also I wonder if we want to import other files than js, json, css, less, styl, scss, sass.

Also I hope that something like importing the file which imports another file from the same level 'node_modules' will still work. But this is probably fourseven:scss (and other build plugins) competence.

In the future it'll be cool to have something like Webpack's css and images loaders, also CSS Modules. To build better separation of components. But this is for the future I gues).

@queso
Copy link
Contributor

queso commented Feb 4, 2016

@thatgibbyguy is your scss.json file support to get it working with the current beta-5 build of Meteor? It still acts like it can't find the file to import when I try it.

@queso
Copy link
Contributor

queso commented Feb 4, 2016

Also, this is unclear @benjamn is this going to be worked on before release, or no? Because Meteor 1.3 completely breaks the zurb:foundation-sites package and doesn't seem to work at all with the NPM version of foundation for @import. Seems like a deal breaker for a lot of people.

@thatgibbyguy
Copy link

@queso there is one caveat with scss.json (and I cannot find documentation on this for the life of me) where you need to rebuild meteor before you can utilize what you've set in scss.json.

So what this means is comment out your imports in your main sass file and restart meteor. After that your imports should work fine.

@juliancwirko
Copy link
Contributor Author

@queso zurb:foundation-sitesis broken in 1.3 because of motion-ui usage. There is a discussion here: foundation/foundation-sites#7896 If we have proper imports from npm_modules I think we don't need Meteor package (zurb:foundation-sites). If there will be no possibility to import .scss files from node_modules then we need to remove motion-ui from zurb:foundation-sites and create a standard separated meteor package for example zurb:motion-ui.

It was done like that because in the past motion-ui was required by some of foundation's js plugins and there wasn't a simple way to include it. Now it isn't required. So I gues that Foundation team will wait for Meteor 1.3 official release. Because for now there isn't a clear path what should be done. Personally I prefer abandon zurb:foundation-sites and make usage of npm package ;) But without proper imports in .scss files from node_modules it won't work that way. So, yeah, this is a deal breaker in this case and many similar.

@queso
Copy link
Contributor

queso commented Feb 4, 2016

@juliancwirko yeah, I saw that, and I agree that the proper way forward is to use the npm version because it will reduce load on outside projects having to care how Meteor compiles and/or packages files.

@queso
Copy link
Contributor

queso commented Feb 4, 2016

@thatgibbyguy sorry to be dense, but I added the scss.json file to the root of my 1.3 app and restarted everything. Still no luck:

While processing files with fourseven:scss (for target web.browser):
   /client/stylesheets/main.scss: Scss compiler error: File to import: {}/client/stylesheets/foundation-sites/scss/foundation.scss not found in file: /Users/josh/Code/Clients/clientA/{}/client/stylesheets/main.scss

My main.scss file is just this:

@import 'foundation-sites/scss/foundation.scss';

@sebakerckhof
Copy link
Contributor

I think @thatgibbyguy uses the old meter-scss (v1.2) plugin. Because later versions don't use scss.json anymore. That old version kind of bypasses the meteor compiler system and just reads the files from disk itself. It also doesn't support cross-package references.

@thatgibbyguy
Copy link

@sebakerckhof is right. I'm using fourseven:scss@=3.2.0

@sebakerckhof
Copy link
Contributor

@thatgibbyguy Yeah, 3.2 is what I meant to say. The changes I describe are from 3.3 up.

@ffxsam
Copy link
Contributor

ffxsam commented Feb 22, 2016

IMO we really need a solution for this. I'm trying to use materialize-css with material-ui (NPM) and not having any luck. I either have to include materialize-css via HTML, which causes collisions with material-ui, or add the meteor package which has the same problem. I just want to be able to use @import to include what I need. And I can't get help from anywhere else, because most people still don't know about Meteor, and make suggestions like using webpack or some other solution that we Meteor (1.3) folks don't need to worry about.

@zol zol removed the desired label Feb 23, 2016
@bySabi
Copy link

bySabi commented Mar 2, 2016

Meteor 1.3 is almost useless without node_modules assets import.
IMHO this must be solved on 1.3 and I don´t undestand why is scheduled after on 1.3.1 or beyond.

Right now I'm trying a 1.3 project integration with https://github.com/thereactivestack/meteor-webpack only for import .scss files from node_modules and only have errors and meteor fatigue

Please MDG make a last effort on this ...

@123ndy
Copy link

123ndy commented Mar 7, 2016

I agree with @ffxsam, @bySabi and the rest of the coders in here. I also have issues with this, and would love to see it in one of the near 1.3 beta releases.

We believe in you MDG <3

@skirunman
Copy link
Contributor

skirunman commented Apr 18, 2016

If the second option above does not work then I think maybe it would make sense to focus the conversation on your #6846 and see if we can get this fixed or implemented as a new feature.

@trusktr
Copy link
Contributor

trusktr commented Apr 28, 2016

@benjamn I like @thatgibbyguy's suggestion, relative to the app root, but absolute paths could point anywhere:

{
  "includePaths": [
    "node_modules/some/path/"
  ]
}

Are you guys averse to allowing some sort of configuration like this?

@wimvanloocke
Copy link

Hi,
try to setup meteor 1.3.2.4 and react
when just doing an import "/font-awesome/css/font-awesome.css"; in my jsx file i see when debugging in the browser there is a section in the indicating awesome as text/css style. (like bootstap) However the fonts are not found. Something wrong with path's? I also see path indicating ../fonts, and read something about fa-font-path but don't see a way out.

@juliancwirko
Copy link
Contributor Author

@wimvanloocke importing .css file in .js file adds the contents of that .css file to the <head> so you probably need to put your font files in /public/fonts folder and change the font path in .css file to the /fonts. Anyway I wonder if this is a way to go, maybe it will be simpler to just place font-awesome.css file outside the imports folder or just use CDN for that. You can also use .scss or .less version of font-awesome and import it in your .less or .scss files instead in .js file.

@wimvanloocke
Copy link

Maybe your right but i don't want to mess up and use a lot of different methods. Why does it work for imports of bootstrap, adminlte,.. and not for font-awesome,... do i miss an import / dependency. Is font-awesome not "build" for using this way?

@tcastelli
Copy link
Contributor

tcastelli commented May 5, 2016

If you place the font files in public/fonts and the library that you want to use is using an absolute route like@import /fonts/xxxxx.wotf for example, it can work(assuming that you copy the fonts files to your public folder).Otherwise, If the library is looking for the file with a relative path like @import ../fonts/xxxx.wotf, then it won't work, since the final route doesn't match where you have placed the fonts and there are there are a few solutions for that.

  • Modify the original css changing every import and changing ../fonts for /fonts and place the new css file inside your code normally-> Pain to keep updated but fast and easy
  • Import all css from CDN in your <head> </head>. This is quite useful if you don't have load order problems but remember the final code will have 1st merged styles from your css/atmosphere packages, 2nd those from CDN and 3rd the ones imported through javascript. If you are mixing different sources this can be a pain in the... to control, but if you can load all your css from CDN then it is easy to control the load order and really fast(as long as there aren't hundreds of css files/files to load)
  • Import everything with the package mizzao:build-fetcher or similar. This is a not so common use, but will allow you to place the css files and font files in the correct folders and all the css will be placed in your merged stylesheets(so at the beginning of everything). -> This is not as fast as using CDN because you serve the content, but it helps to get everything on its place, and is also not hard to update. However, you can't check for dependencies or updates automatically (which is handy is you use npm)

So basically, there's no easy way right now to import source files from npm packages that involve css and font files (or something different than less, sass or stylus), especially when they are using relative paths on @imports. In those cases, atmosphere packages like meteor add tws:bootstrap or the previous solutions can help until we have a native feature for that (hopefully soon)

@honwlt
Copy link

honwlt commented May 6, 2016

If you have sym links to npm's font folders in the public folder, then meteor would not serve any static files (img & fonts) under public. May be a bug?

You have to copy the npm's fonts folder to public & have it referenced as /fonts to work.
It's just painful & maintenance nightmare.
BTW, I am on 1.3.2.4

@ephemer
Copy link

ephemer commented Jun 27, 2016

@benjamn I'm not sure this issue should be closed. From what I understand you closed this because meteor now allows importing css files via javascript into <head>. Is this really the best practice solution?

To me it feels like a hack at best and not a great developer experience (why import all of our styles in main.less except some random npm package's css?) It also seems like we're missing out on the possibility to see unminified CSS in development and still have the css bundled and minified in production.

@laosb
Copy link
Contributor

laosb commented Sep 15, 2016

Still getting:

=> Errors prevented startup:

   While processing files with less (for target web.browser):
   client/main.less:8: Unknown import: {}/node_modules/zoaui/css/form.css

=> Your application has errors. Waiting for file change.

@adinutzyc21
Copy link

adinutzyc21 commented Nov 19, 2016

Edit:import 'react-bootstrap-table/css/react-bootstrap-table.css'; seems to work from the jsx file, which is good enough for me. However, I was definitely not able to import it from css... (tried all permutations from here #6037 (comment))

Anyone fix this? I'm on 1.4.2.3 and importing css files doesn't work from node_modules(I'm not talking less or sass). I was convinced I was doing something wrong, so I copied the file to my own file and, magic, it works :(

But I'm trying to use bootstrap, and copying all stylesheets kind of defeats the purpose. Am I doing something wrong and y'all fixed it? Should I do a package.js file? This is my absolute first app and I seriously have no idea what I'm doing...

@s-devaney
Copy link

Haven't found a solution to importing a .css file through another CSS file. I'm not happy either about having to import it via a JS file.

@nosizejosh
Copy link

nosizejosh commented May 25, 2017

is this feature (import css from node modules) implemented in any release of meteor?

@dandv
Copy link
Contributor

dandv commented Mar 3, 2018

OK, so what's the TL;DR two years later? How can I import a .CSS file from an npm package? Is it only possible via JS while #6846 is getting fixed?

@thatgibbyguy
Copy link

thatgibbyguy commented Mar 3, 2018

@dandv - yes with 1.6 it's much easier. I've recently started playing around with it and I'll show you how it's done.

After updating meteor meteor update you can import like so:

@import "{}/node_modules/plygrid/src/scss/_ply.scss";

Simple as that. (note, this is with the latest fourseven:scss)

@dandv
Copy link
Contributor

dandv commented Mar 3, 2018

@thatgibbyguy: I'm on Meteor 1.6.1 and I've meteor npm installed rmwc.

Added this to client/main.css but in DevTools I see that meteor serves / instead of the CSS:

@import '{}/node_modules/material-components-web/dist/material-components-web.css';

If I add this to main.js, the CSS does load:

import 'material-components-web/dist/material-components-web.css';

@livimonte
Copy link

I'm also importing in the main.js.

@dandv have you tried with postcss? #6846 (comment)

It has not yet been solved completely but seems to help in some cases.

They migrated this to the feature request repository now: meteor/meteor-feature-requests#278

benjamn pushed a commit that referenced this issue Apr 5, 2018
Although there was a comment in this code about not applying .meteorignore
files to the contents of node_modules directories, I'm pretty sure that
was the wrong decision, because .meteorignore merely limits what Meteor
tries to compile as application code, and does not actually modify or hide
node_modules files from other parts of Meteor (or Node).

In other words, there's no harm in letting .meteorignore apply to
node_modules, and there may be a LOT of benefit, because it allows the
developer to fight back when compilation descends unexpectedly into an npm
package that contains non-.js[on] files for which a compiler plugin has
been registered, an obscure but not uncommon behavior originally intended
to allow importing CSS assets from npm packages:

* #6037
* 43659ff
* a073280
* #5242
* #6846
* #7406

However, we now have a much more powerful tool for selectively compiling
specific npm packages: #9771. In light of this new approach, we should
probably remove the promiscuous node_modules compilation behavior
altogether, as it might speed up rebuild times for many applications whose
developers don't know or care that this behavior exists. For example,
abandoning this behavior would prevent the problem reported here:
#6950

In the meantime, this commit makes .meteorignore work for node_modules.
benjamn added a commit that referenced this issue Apr 5, 2018
…es. (#9800)

Although there was a comment in this code about not applying .meteorignore
files to the contents of node_modules directories, I'm pretty sure that
was the wrong decision, because .meteorignore merely limits what Meteor
tries to compile as application code, and does not actually modify or hide
node_modules files from other parts of Meteor (or Node).

In other words, there's no harm in letting .meteorignore apply to
node_modules, and there may be a LOT of benefit, because it allows the
developer to fight back when compilation descends unexpectedly into an npm
package that contains non-.js[on] files for which a compiler plugin has
been registered, an obscure but not uncommon behavior originally intended
to allow importing CSS assets from npm packages:

* #6037
* 43659ff
* a073280
* #5242
* #6846
* #7406

However, we now have a much more powerful tool for selectively compiling
specific npm packages: #9771. In light of this new approach, we should
probably remove the promiscuous node_modules compilation behavior
altogether, as it might speed up rebuild times for many applications whose
developers don't know or care that this behavior exists. For example,
abandoning this behavior would prevent the problem reported here:
#6950

In the meantime, this commit makes .meteorignore work for node_modules.
@livimonte
Copy link

I made a PR with CSS imports working with POSTCSS in this Meteor React boilerplate from @juliancwirko. If you're having trouble making it work, take a look. It has the SCSS preprocessor working along with the POSTCSS as well.
https://github.com/juliancwirko/scotty

@andrewlorenz
Copy link

I've tried every option and workaround on this thread and nothing ain't working. Seems like a whole pile of doggy doo to me, npm packages from all over incorporate their own css which you need to import (and yes I mean css, not scss), and yet it seems MDG have ignored it despite getting all excited about whether it would make version 1.3 or have to wait until the first patch two-and-a-half years ago ??!

@thatgibbyguy
Copy link

@andrewlorenz I've got it working just fine. Here's what I've got:

  • Meteor 1.7.0.3
  • fourseven:scss (latest)
  • plygrid (npm install plygrid)

In /client/css/main.scss :

@import "{}/node_modules/plygrid/src/scss/_ply.scss";

Of course you may be using vanilla css and I wouldn't know how to incorporate that other than putting it in public and just writing vanilla css in client. Seems like you could have two working options here.

@leosco
Copy link

leosco commented Sep 26, 2018

Hi all, please see @livimonte 's comment above. For vanilla CSS, not SCSS or LESS, you should import it from your node_modules by in your ./client/ js source.

Here's an example of a ./client/main.js using the npm package materialize-css -

import 'materialize-css/dist/js/materialize.min';  // omit the .js
import 'materialize-css/dist/css/materialize.min.css';  // non-js imports have the extension

Using @import url() in your main.css doesn't work for node_modules sources, because that usage depends on installing a third party pre-processor. Instead, just import it directly into a client JS file and ecmascript figures it out.

Please do some research before spamming the issue boards, it's even in the official guide!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests