maoberlehner / node-sass-magic-importer

Custom node-sass importer for selector specific imports, module importing, globbing support and importing files only once.
MIT License
292 stars 28 forks source link

LibSass DEPRECATION WARNING #181

Closed Grawl closed 5 years ago

Grawl commented 6 years ago

Each time I compile Sass there is a warning from LibSass:

DEPRECATION WARNING on line 5, column 8 of /Users/prn/Sites/unqm-markup/public/source/style.scss:
Including .css files with @import is non-standard behaviour which will be removed in future versions of LibSass.
Use a custom importer to maintain this behaviour. Check your implementations documentation on how to create a custom importer.
maoberlehner commented 6 years ago

Hey @Grawl,

this is a deprecation warning from LibSass read more about it here: https://github.com/sass/node-sass/issues/2362

Does this answer your question? Because I'm not quite sure what you expect me to do about this 😅

JacobDB commented 6 years ago

@maoberlehner I'm also having this issue and having a hell of a time figuring out a solution. I've already read through the thread you linked and a couple of others that were related, but it doesn't seem like any real resolution is coming any time soon. node-sass said they'll remove the warning in v4.10, but that was back in July with no real update since, and the thread is locked.

I think @Grawl is posting here because this module has to do with custom importers, although it's probably not the best place for it. Still, given that you have some experience with this, do you have any suggestions on where to find such a custom importer, or how to write one, to remove this warning?

It's extremely frustrating that this even became an issue, because we have no control over what type of files third-party packages choose to deliver, and so can't simply stop importing .css files.

Grawl commented 6 years ago

@JacobDB thank you for such an explained comment here. Words you write is what I want to say but have no time when I created this issue.

Some time ago, I didn't know that LibSass can inline @import. So I use postcss-import to inline .css files into my bundles. If LibSass turn off this feature, my bundle will not change.

To get rid of deprecation warning, I tried to use node-sass-css-importer as a custom importer with node-sass-magic-importer. But this two custom importers is not compatible.

I cannot write things like this:

@import 'CSS~vue-multiselect/dist/vue-multiselect.min.css';

It's not work.

maoberlehner commented 6 years ago

To get rid of deprecation warning, I tried to use node-sass-css-importer as a custom importer with node-sass-magic-importer. But this two custom importers is not compatible.

Yeah, unfortunately, combining multiple custom importers is not really possible.

I understand that this is unfortunate for you but I don't have plans on supporting CSS imports with this library because it's not something I'm interested in and my time is very limited.

I might consider accepting a pull request if it's possible to add this functionality without adding too much additional complexity.

JacobDB commented 6 years ago

@Grawl I was able to whip something together this morning that suits my needs, hopefully it does for you as well.

const FS   = require("fs");
const GLOB = require("glob");
const SASS = require("gulp-sass");

.pipe(SASS({
    importer: (url, prev, done) => {
        // ensure the imported file isn't remote, doesn't have an extension specified, or is a .css file
        if (url.match(/^(?!https?:\/\/)[^.]+(\.css)?$/)) {
            // get the path to the folder containing the importing file
            const PREV_PATH = prev.replace(new RegExp(/\/[^./]+\.(sass|scss)$/), "") + "/";

            // construct a glob pattern based on the importing path and url to the imported file
            const GLOB_PATTERN = (url) => {
                const PATH = url.replace(new RegExp(/[^/]+$/), "");
                const FILE = url.replace(new RegExp(/^.*\/([^.]+)/), "$1");

                return "{" + PREV_PATH + "," + "./node_modules/}" + PATH + "?(_)" + FILE + ".css";
            };

            // try to find a matching file
            const GLOBBED = GLOB.sync(GLOB_PATTERN(url));

            // ensure only one result was matched; let node-sass handle the "It's not clear" error
            if (GLOBBED.length === 1) {
                // return the contents of the imported file
                return done({contents: FS.readFileSync(GLOBBED[0], "utf8")});
            }
        }

        return done();
    },
    includePaths: "./node_modules",
    outputStyle:  "nested",
}))
JacobDB commented 6 years ago

Thinking about making the above in to an easily installable module, but would like to able to read includePaths from the Sass options; @maoberlehner I know we're getting a bit off topic here, but would you know how to achieve that?

Grawl commented 6 years ago

Thank you @JacobDB! This looks like sort of success.

But I suggest to use path tools instead of regular expressions to work with path strings.

JacobDB commented 6 years ago

Ah, I'm pretty new to writing my own Node.js stuff like this so I wasn't aware there was a better way, I'll look in to it when I have a bit more time :)

maoberlehner commented 6 years ago

Thinking about making the above in to an easily installable module, but would like to able to read includePaths from the Sass options; @maoberlehner I know we're getting a bit off topic here, but would you know how to achieve that?

No problem, I think it's great that you're helping each other (and potential others) here 👍

In order to access the node-sass includePaths you have to change your code to not use an arrow function.

const FS   = require("fs");
const GLOB = require("glob");
const SASS = require("gulp-sass");

.pipe(SASS({
    importer: function cssImporter(url, prev, done) {
      // ...
      // If you're using an arrow function, you don't have access to `this`.
      console.log(this.options.includePaths);
      // ...
    },
    includePaths: "./node_modules",
    outputStyle:  "nested",
}))
JacobDB commented 6 years ago

@maoberlehner awesome, thanks for that!

@Grawl how's this?

const FS   = require("fs");
const GLOB = require("glob");
const PATH = require("path");
const SASS = require("gulp-sass");

// compile SCSS (compress if --dist is passed)
.pipe(SASS({
    importer: function (url, prev, done) {
        const EXT  = PATH.extname(url);
        const PATH = PATH.dirname(url);
        const FILE = PATH.basename(url, EXT);
        const PREV = PATH.dirname(prev);

        // ensure the imported file isn't remote, doesn't have an extension specified, or is a .css file
        if (!url.match(/^https?:\/\//) && (EXT === "" || EXT === "css")) {
            // build out glob pattern based on PREV and includePaths
            const INCLUDE_PATHS = "{" + PREV + "," + this.options.includePaths.replace(new RegExp(/:/g), ",") + "}";

            // try to find a matching file
            const GLOBBED = GLOB.sync(INCLUDE_PATHS + "/" + PATH + "/" + FILE + ".css");

            // ensure only one result was matched; let node-sass handle the "It's not clear" error
            if (GLOBBED.length === 1) {
                // return the contents of the imported file
                return done({contents: FS.readFileSync(GLOBBED[0], "utf8")});
            }
        }

        return done();
    },
    includePaths: "./node_modules",
    outputStyle:  "nested",
}))
JacobDB commented 6 years ago

Set it up as my first published custom module :smile: https://www.npmjs.com/package/node-sass-simple-css-importer

gilsdav commented 6 years ago

adding url() around the css import fixed the problem form me

JacobDB commented 6 years ago

@gilsdav that just makes it a standard CSS import, which is fine if you're uploading the file you're importing, but for my use case I needed to be able to import from node_modules, which I don't upload to my servers.

Grawl commented 6 years ago

@gilsdav thank you! how can I forget I doing like this earlier 😅

@JacobDB so use postcss-import

JacobDB commented 6 years ago

@Grawl I did try that but ran in to more issues and it seemed like more trouble than it was worth.

maoberlehner commented 5 years ago

Closing this, because there seems to be a solution for the problem and it's not directly related to this package. Thank you guys for helping each other out 👍

nlemoine commented 5 years ago

I might consider accepting a pull request if it's possible to add this functionality without adding too much additional complexity.

@maoberlehner Would you agree if I submit a PR to implement this in node-sass-magic-importer?

I try to get rid of those annoying deprecation warnings as well and would like to be able to import .{sass,scss} or .css files.

nlemoine commented 5 years ago

Just in case, it's ready to PR if you want to have a look: https://github.com/nlemoine/node-sass-magic-importer/tree/feature/fix-libsass-css-import