Skip to content

Conversation

jamestalmage
Copy link

@jamestalmage jamestalmage commented Jan 5, 2019

UPDATE: Only discussing the fixes to relative imports here. See #31 for the percent char issue fix as a separate PR.

The fix for includePaths included in v1.0.0 breaks all relative imports.

While investigating a proper fix, I also noticed that one of the existing tests was failing in node-sass@4.11 (but worked fine in node-sass@4.10). For some reason, placeholders immediately followed by a % char were causing syntax errors.

I fixed the % char problem in the first commit, and relative imports in the second. Both commit comments contain more detailed explanations.

The relative @import fix should definitely be incorporated.

I suspect the other might actually just be a node-sass bug (I don't know enough about the syntax to say for sure). That said, It's a 4 line fix that's easy enough to back out later.

Copy link
Owner

@giuseppeg giuseppeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the PR! can you split it up in two? I like to keep them scoped


assert.equal(
plugin(file.toString(), {
sassOptions: {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should keep this I guess, tests should still pass with the old setup

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that test explicitly uses a relative import (i.e. starts with ./). The expected behavior is that it will resolve relative to the current file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words. The test as is, is verifying an undesirable behavior. You shouldn't have to add to includePaths if you're explicitly using ./ to signal a relative path.

const optionData = settings.sassOptions && settings.sassOptions.data || "";
const data = optionData + "\n" + cssWithPlaceholders;

const file = settings.babel && settings.babel.filename;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this, I thought with v1 we agreed that this should work when setting the includePath via sassOptions. cc @atombender

Copy link
Author

@jamestalmage jamestalmage Jan 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative paths do not work properly in v1, they can easily resolve to the wrong file if you have two files with the same name in different directories

# directory structure
components
  foo-component
    styles.scss
    foo-component.js    # @import './styles'
  bar-component
    styles.scss
    bar-component.js    # @import './styles' 
sassOptions.includePaths = [
  "components/foo-component",
  "components/bar-component"
]

In this scenario, with your current implementation, it is going to search in order of the includePaths. This means both imports will resolve to the file inside foo-component. That's definitely not what bar-component wanted.

I am happy to add a regression tests that proves all that ⬆️ if it increases your comfort level, but we're really just testing node-sass implementation details at that point. The test as I've got it checks that explicit relative imports will work without modifying includePaths.

The problem you resolved in v1 was that you were clobbering the users intended includePaths settings in an effort to get relative paths to work.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha thank you for the exhaustive explanation. How do you solve this issue in a standalone node-sass setup?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with the current implementation is that node-sass doesn't know the file location, it is only being provided the files contents. In a standalone node-sass setup, that would never happen (it's reading in the file contents itself, and it already knows the file path from the CLI or config).

This is simply giving node-sass the extra bit of information it needs to process the @import command properly.

Previous attempts to allow relative paths in @import statements added
to `sassOptions.includePaths`. That was deemed unacceptable as it would
capture relative files that weren't explicitly imported with relative paths.

The solution is to pass the filename in `sassOptions`. It's fine to pass
the javascript file path: we are already providing the `data` option with
the content to parse, so sass won't actually try to read the file. It is only
used for resolving explicit relative imports.
@jamestalmage jamestalmage changed the title Fix relative imports, and node-sass 4.11 breakage. Fix relative imports. Jan 19, 2019
@jamestalmage
Copy link
Author

jamestalmage commented Jan 19, 2019

Just so we're clear. The previous attempt to make relative imports work went about it by adding the files location to includePaths:

if (settings.babel && settings.babel.filename) {
includePaths.push(path.dirname(settings.babel.filename));
}

That wasn't a great implementation:

  1. It pushed the path at the end of includePaths, so it was looking in the same directory last, instead of first.
  2. It did not make a defensive copy of includePaths, but kept appending to the end, so the contents of includePaths was dependent on file traversal order, and it would keep growing over time on the server end.

This implementation does not suffer from either of those pitfalls.

jitterbugboy pushed a commit to jitterbugboy/styled-jsx-plugin-less that referenced this pull request Jan 25, 2019
- same solution as giuseppeg/styled-jsx-plugin-sass#30 follow up on that one to see if any problems is related
martonlederer referenced this pull request in martonlederer/styled-jsx-plugin-sass-2 Nov 1, 2020
Co-Authored-By: James Talmage <james@talmage.io>
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

Successfully merging this pull request may close these issues.

2 participants