question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ship a built-in package importer

See original GitHub issue

There’s currently no standard way for Sass users to import packages from dependencies. There are a number of domain-specific solutions, such as Webpack’s tilde-based imports, npm-sass’s load-path-like functionality, or Dart Sass’s support for Dart’s package: URLs.

Most of these have the disadvantage of needing to be explicitly opted-into, and all of them make it difficult to share stylesheets across different contexts. For example, if package A depends on package B, how can A import B in a way that will work in both Webpack and in Dart?

This is the kind of situation where centralization is a boon. If we can build into the Sass language a notion of a “package import” that’s flexible enough to work across contexts, we can make it usable by all stylesheets with confidence that even if they’re used by different build runners or even ported to a different package manager their dependencies will continue to work.

What does it look like?

The Sass specification talks about imports in terms of URLs. The current JS API deals with them as a combination of raw strings and filesystem paths, but I’d like to move away from that as part of #2509.

The current most popular solution for package imports is probably sass-loader’s, which passes any import that begins with ~ through Webpack’s built-in resolution infrastructure. We could re-use this syntax, but it doesn’t work well with URL semantics. A string beginning with a tilde is syntactically a relative URL, which means we’d need to check for the relative path ~package first before passing the URL to the package importer.

We’d have a similar problem if we automatically added node_modules to the load path. Every instance of @use "bootstrap" would need to check the relative path first, as well as potentially every load path, before checking the package importer. It also makes package stylesheets less visually distinctive, which can be confusing for readers.

As such, I propose that we use the URL scheme pkg: to indicate Sass package imports, so users would write @use "pkg:bootstrap". This doesn’t conflict with any existing syntax and so producing backwards-compatibility headaches, and it nicely mirrors the syntax of Sass’s core libraries (@use "sass:color").

What does it do?

The purpose of a standard package importer is in fact to avoid specifying the exact behavior of the importer, so that it can do something sensible for each context. However, since Node.js is by far the most popular context in which Sass is used, we should figure out what it does in that particular case.

When resolving a URL, I think it should check node_modules folders as described in Node’s documentation, beginning from the parent directory of the module in which Sass is invoked (if it’s invoked as a library from JS) or the parent directory of the entrypoint file (if Sass is invoked via the command line).

There’s a convention of npm packages declaring their Sass entrypoints using "style" or "sass" keys in their package.json. While it’s definitely useful to be able to write @import "bootstrap" rather than @import "bootstrap/scss/bootstrap", I actually think we shouldn’t support this. Instead, I think we should encourage packages to define an _index.scss file that acts as the entrypoint. This will ensure that even if the package ends up on the load path, or installed through some way other than node_modules, it can still be imported correctly without needing to parse package.json.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:35
  • Comments:22 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
KaelWDcommented, Jun 11, 2022

Supporting conditional exports would be nice too, so my library can specify

"exports": {
  "./styles": {
    "sass": "./lib/styles/main.scss",
    "default": "./dist/main.css"
  }
}

to make @use 'library/styles' load the scss file but import 'library/styles' load precompiled css instead.

4reactions
nex3commented, Dec 17, 2019

@Cleecanth One of the major goals of this plan is to avoid tightly coupling source files to particular host environments. If users are writing npm: or node: in their @use URLs, then the files that contain those URLs are only usable in an npm or Node context.

The point of a pkg: scheme is that it can be resolved differently in different contexts. If you’re using npm, it can be resolved using the node_modules directory, but if you’re using Ruby it can be resolved using Bundler logic or whatever.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Importing Packages in Go - DigitalOcean
This tutorial will walk you through installing, importing, ... we import packages we're able to call functions that are not built in to...
Read more >
Importing an Asset Store package - Unity - Manual
See Importing a complete project from the Asset Store. For all other Asset Store packages, the Import Unity Package window displays all the...
Read more >
Import declarations in Go - Medium
Built-in packages are imported with short import paths like "math" or "fmt" . Anatomy of .go file. Structure of every .go file is...
Read more >
Python import: Advanced Techniques and Tips
Modules; Packages; Absolute and Relative Imports; Python's Import Path ... as a submodule within a package, then it won't shadow the built-in module....
Read more >
4. Package structure and distribution
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', ... When importing a package or module, Python searches for it in the default list ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found