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

Source maps #74

Open
elektronik2k5 opened this issue Apr 11, 2018 · 4 comments
Open

Source maps #74

elektronik2k5 opened this issue Apr 11, 2018 · 4 comments
Assignees

Comments

@elektronik2k5
Copy link

elektronik2k5 commented Apr 11, 2018

Hi @streamich,

Awesome and thorough work on this! :) I believe css-in-js is the future and am always glad to see new and ambitious projects.
I also like how everything is optional, pluggable and that nothing is opinionated and that it is framework/runtime agnostic.

I realize it's a new project and probably still lacks some features, and I bet you've got a list of these too :). One thing which I personally, can't live without in css-in-js (and JS transpilers) is source maps.
In the world of css-in-js, I've only used styled-components and emotion so far. The latter supports source maps, while the former doesn't. To me, it is such a detrimental feature that I may switch from styled to emotion in a large project I lead.

Hope you add source maps to nano-css at some point. I'll be keeping an eye on your project, since it seems promising.

@streamich
Copy link
Owner

@elektronik2k5 what do you think about having devtools for CSS, like a panel in Kuker?

krasimir/kuker#6

@elektronik2k5
Copy link
Author

Thanks for introducing me to Kuker.

In my view, it is an interesting tool, but by no means a replacement for source maps.
Source maps "just work" in all modern browsers, while Kuker requires both app runtime and an extension. That is a very high barrier to entry - just to inspect styles.

They can be complementary tools though.

@streamich
Copy link
Owner

streamich commented May 1, 2018

Example source map implementation:

/* eslint-env browser */

import StackTrace from "stacktrace-js";
import {encode} from "sourcemap-codec";

const cache = {};

const schedule = window.requestIdleCallback
  ? task => window.requestIdleCallback(task, {timeout: 180})
  : window.requestAnimationFrame;

let counter = 0;
let queue = [];
let debugEnabled = false;

export function enableDebug() {
  debugEnabled = true;
}

export function addDebugClass(baseStyletron, stackIndex) {
  if (!debugEnabled) {
    return;
  }
  const {className, selector} = getUniqueId();
  baseStyletron.debugClass = className;

  const trace = getTrace();

  trace
    .then(stackframes => {
      const {fileName, lineNumber} = stackframes[stackIndex];
      addToQueue({selector, lineNumber, fileName});
    })
    .catch(err => console.log(err)); // eslint-disable-line no-console
}

function flush() {
  const {rules, segments, sources} = queue.reduce(
    (acc, {selector, lineNumber, fileName}) => {
      let sourceIndex = acc.sources.indexOf(fileName);
      if (sourceIndex === -1) {
        sourceIndex = acc.sources.push(fileName) - 1;
      }
      acc.rules.push(`${selector} {}`);
      acc.segments.push([[0, sourceIndex, lineNumber - 1, 0]]);
      return acc;
    },
    {rules: [], segments: [], sources: []},
  );
  queue = [];

  const mappings = encode(segments);
  const map = {
    version: 3,
    sources,
    mappings,
    sourcesContent: sources.map(source => cache[source]),
  };

  const json = JSON.stringify(map);
  const base64 = window.btoa(json);

  const css =
    rules.join("\n") +
    `\n\/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${base64} */`;
  const style = document.createElement("style");
  style.appendChild(document.createTextNode(css));
  document.head.appendChild(style);
}

function addToQueue(item) {
  const prevCount = queue.length;
  queue.push(item);
  if (prevCount === 0) {
    schedule(flush);
  }
}

function getTrace() {
  return StackTrace.get({sourceCache: cache});
}

function getUniqueId() {
  const id = counter++;
  const className = `__debug_${id}`;
  return {
    selector: `.${className}`,
    className,
  };
}

@streamich streamich self-assigned this May 3, 2018
@streamich streamich changed the title Feature request: source maps Source maps May 16, 2018
@streamich
Copy link
Owner

Add sourcemaps addon: https://github.com/streamich/nano-css/blob/master/docs/sourcemaps.md

Tell me if it works for you!

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

2 participants