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

CSS not generated inside var a = function a() {...} #1312

Open
yume-chan opened this issue Aug 2, 2023 · 2 comments
Open

CSS not generated inside var a = function a() {...} #1312

yume-chan opened this issue Aug 2, 2023 · 2 comments
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler needs: complete repro 🖥️ Issue need to have complete repro provided

Comments

@yume-chan
Copy link

yume-chan commented Aug 2, 2023

Environment

  • Linaria version: 4.5.4
  • Bundler (+ version): Vite 4.4.7, Webpack 5.75.0
  • Node.js version: v18.17.0
  • OS: Windows

Description

a.js:

import {css} from '@linaria/atomic'

export const a = function a() {
    return css`
        background-color: red;
    `
}

b.js:

import { a } from "./a";

export default function App() {
  return <div className={a()}>Hello World!</div>;
}

css template string in a() will be replaced with names, but the CSS rules won't be generated.

function isTagReferenced(path: NodePath): boolean {
// Check if the variable is referenced anywhere for basic DCE
// Only works when it's assigned to a variable
let isReferenced = true;
const parent = path.findParent(
(p) =>
p.isObjectProperty() ||
p.isJSXOpeningElement() ||
p.isVariableDeclarator()
);
if (parent) {
if (parent.isVariableDeclarator()) {
const id = parent.get('id');
// FIXME: replace with id.isReferencedIdentifier()
if (id.isIdentifier()) {
const { referencePaths } = path.scope.getBinding(id.node.name) || {
referencePaths: [],
};
isReferenced = referencePaths.length !== 0;
}
}
}
return isReferenced;
}

parent is the const a node, but path.scope.getBinding(id.node.name) returns the function a() node. function a() node has no references so CSS extraction was skipped.

This code is simplified from an output of Solid.js babel plugin, so it can't change.

Reproducible Demo

https://codesandbox.io/p/sandbox/interesting-brook-vn8dgp

@yume-chan yume-chan added bug report 🦗 Issue is probably a bug, but it needs to be checked needs: complete repro 🖥️ Issue need to have complete repro provided needs: triage 🏷 Issue needs to be checked and prioritized labels Aug 2, 2023
@github-actions github-actions bot added bundler: webpack 📦 Issue is related to webpack bundler and removed needs: triage 🏷 Issue needs to be checked and prioritized labels Aug 2, 2023
@yume-chan
Copy link
Author

The actual code given to Linaria is:

Expand
import { template as _$template } from "solid-js/web";
import { className as _$className } from "solid-js/web";
import { getNextMarker as _$getNextMarker } from "solid-js/web";
import { createComponent as _$createComponent } from "solid-js/web";
import { getNextElement as _$getNextElement } from "solid-js/web";
import { insert as _$insert } from "solid-js/web";
import { effect as _$effect } from "solid-js/web";
import { setAttribute as _$setAttribute } from "solid-js/web";
import { $$component as _$$component } from "solid-refresh";
import { $$refresh as _$$refresh } from "solid-refresh";
import { $$registry as _$$registry } from "solid-refresh";
const _REGISTRY = _$$registry();
const _tmpl$ = /*#__PURE__*/_$template(`<option disabled hidden selected>`),
  _tmpl$2 = /*#__PURE__*/_$template(`<label><!#><!/><div><select><!#><!/><!#><!/></select><!#><!/>`);
import { css, cx } from "@linaria/atomic";
import { Show, createUniqueId } from "solid-js";
import { rem, theme } from "~/utils/theme";
import { AddClassList, FluentChevronDown16Regular } from "./icons";
export const Select = _$$component(_REGISTRY, "Select", function Select(props) {
  const id = createUniqueId();
  return (() => {
    const _el$ = _$getNextElement(_tmpl$2),
      _el$11 = _el$.firstChild,
      [_el$12, _co$4] = _$getNextMarker(_el$11.nextSibling),
      _el$2 = _el$12.nextSibling,
      _el$3 = _el$2.firstChild,
      _el$5 = _el$3.firstChild,
      [_el$6, _co$] = _$getNextMarker(_el$5.nextSibling),
      _el$7 = _el$6.nextSibling,
      [_el$8, _co$2] = _$getNextMarker(_el$7.nextSibling),
      _el$9 = _el$3.nextSibling,
      [_el$10, _co$3] = _$getNextMarker(_el$9.nextSibling);
    _$setAttribute(_el$, "for", id);
    _$insert(_el$, () => props.label, _el$12, _co$4);
    _el$3.addEventListener("change", e => props.onChange(e.currentTarget.value));
    _$setAttribute(_el$3, "id", id);
    _$insert(_el$3, _$createComponent(Show, {
      get when() {
        return props.placeholder;
      },
      get children() {
        const _el$4 = _$getNextElement(_tmpl$);
        _$insert(_el$4, () => props.placeholder);
        return _el$4;
      }
    }), _el$6, _co$);
    _$insert(_el$3, _$createComponent(AddClassList, {
      get ["class"]() {
        return css`
              background-color: var(${theme.background});
              color: var(${theme.foreground});
            `;
      },
      get children() {
        return props.children;
      }
    }), _el$8, _co$2);
    _$insert(_el$2, _$createComponent(FluentChevronDown16Regular, {
      get ["class"]() {
        return css`
            position: absolute;
            top: 50%;
            right: ${rem(8)};
            transform: translateY(-50%);
            font-size: ${rem(16)};
            pointer-events: none;
          `;
      }
    }), _el$10, _co$3);
    _$effect(_p$ => {
      const _v$ = cx(css`
          color: var(${theme.foreground});
        `, props.class),
        _v$2 = css`
          position: relative;
          margin-top: ${rem(8)};
        `,
        _v$3 = css`
            appearance: none;
            display: block;
            width: 100%;
            height: ${rem(40)};
            background-color: transparent;
            border-width: 1px;
            border-style: solid;
            border-color: var(${theme.foreground3});
            padding-left: ${rem(12)};
            padding-right: ${rem(12)};
            color: inherit;
            border-radius: 5px;
          `;
      _v$ !== _p$._v$ && _$className(_el$, _p$._v$ = _v$);
      _v$2 !== _p$._v$2 && _$className(_el$2, _p$._v$2 = _v$2);
      _v$3 !== _p$._v$3 && _$className(_el$3, _p$._v$3 = _v$3);
      return _p$;
    }, {
      _v$: undefined,
      _v$2: undefined,
      _v$3: undefined
    });
    _$effect(() => _el$3.value = props.value);
    return _el$;
  })();
}, {
  location: "src\\components\\select.tsx:15:7"
});
if (import.meta.hot) {
  _$$refresh("vite", import.meta.hot, _REGISTRY);
  import.meta.hot.accept();
}

Two styles in get ["class"]() functions are not extracted. Styles in _$effect function are extracted correctly.

I can't share the whole project.

@yume-chan
Copy link
Author

This issue is still reproducible with Linaria v5 (@linaria/babel-preset@5.0.2).

Updated demo: https://codesandbox.io/p/sandbox/elastic-water-4wwgmy

@yume-chan yume-chan changed the title CSS not generated in some cases CSS not generated inside var a = function a() {...} May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler needs: complete repro 🖥️ Issue need to have complete repro provided
Projects
None yet
Development

No branches or pull requests

1 participant