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

transform styled dom component usage for improved performance #154

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/next-yak/runtime/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ export { useTheme, YakThemeProvider } from "next-yak/context";
// runtime internals (helpers which get injected by the compiler)
export { unitPostFix as __yak_unitPostFix } from "./internals/unitPostFix.js";
export { mergeCssProp as __yak_mergeCssProp } from "./internals/mergeCssProp.js";

// export shorthand for DOM styled components (e.g. for styled.div)
export * from "./styledDom.js";
45 changes: 23 additions & 22 deletions packages/next-yak/runtime/styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,13 @@ type Attrs<
| ((p: Substitute<TBaseProps & { theme: YakTheme }, TIn>) => Partial<TOut>);

//
// The `styled()` and `styled.` API
// The `styled()` API without `styled.` syntax
//
// The API design is inspired by styled-components:
// https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/constructors/styled.tsx
// https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/models/StyledComponent.ts
//

const StyledFactory = <T,>(Component: HtmlTags | FunctionComponent<T>) =>
export const StyledFactory = <T,>(Component: HtmlTags | FunctionComponent<T>) =>
Object.assign(yakStyled(Component), {
attrs: <
TAttrsIn extends object = {},
Expand Down Expand Up @@ -192,26 +191,28 @@ type StyledLiteral<T> = <TCSSProps>(
* `;
* ```
*/
export const styled = new Proxy(
StyledFactory as typeof StyledFactory & {
[Tag in HtmlTags]: StyledLiteral<JSX.IntrinsicElements[Tag]> & {
attrs: <
TAttrsIn extends object = {},
TAttrsOut extends AttrsMerged<
JSX.IntrinsicElements[Tag],
TAttrsIn
> = AttrsMerged<JSX.IntrinsicElements[Tag], TAttrsIn>,
>(
attrs: Attrs<JSX.IntrinsicElements[Tag], TAttrsIn, TAttrsOut>,
) => StyledLiteral<Substitute<JSX.IntrinsicElements[Tag], TAttrsIn>>;
};
},
{
get(target, TagName: keyof JSX.IntrinsicElements) {
return target(TagName);
export const styled =
// The proxy adds the styled.div, styled.button, etc. syntax
new Proxy(
StyledFactory as typeof StyledFactory & {
[Tag in HtmlTags]: StyledLiteral<JSX.IntrinsicElements[Tag]> & {
attrs: <
TAttrsIn extends object = {},
TAttrsOut extends AttrsMerged<
JSX.IntrinsicElements[Tag],
TAttrsIn
> = AttrsMerged<JSX.IntrinsicElements[Tag], TAttrsIn>,
>(
attrs: Attrs<JSX.IntrinsicElements[Tag], TAttrsIn, TAttrsOut>,
) => StyledLiteral<Substitute<JSX.IntrinsicElements[Tag], TAttrsIn>>;
};
},
},
);
{
get(target, TagName: keyof JSX.IntrinsicElements) {
return target(TagName);
},
},
);

// Remove all entries that start with a $ sign
function removePrefixedProperties<T extends Record<string, unknown>>(obj: T) {
Expand Down
141 changes: 141 additions & 0 deletions packages/next-yak/runtime/styledDom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { StyledFactory } from "./styled.js";
/// Internal API to create styled components
/// Optimization for faster rendering and smaller bundle size in production
/// thanks to better minification and dead code elimination
///
/// List taken from https://github.com/styled-components/styled-components/blob/e0019ba666fab4b5aaa2bff71ba6ad0005a299fd/packages/styled-components/src/utils/domElements.ts#L90
export const __yak_a = /*#__PURE__*/ StyledFactory("a");
export const __yak_abbr = /*#__PURE__*/ StyledFactory("abbr");
export const __yak_address = /*#__PURE__*/ StyledFactory("address");
export const __yak_area = /*#__PURE__*/ StyledFactory("area");
export const __yak_article = /*#__PURE__*/ StyledFactory("article");
export const __yak_aside = /*#__PURE__*/ StyledFactory("aside");
export const __yak_audio = /*#__PURE__*/ StyledFactory("audio");
export const __yak_b = /*#__PURE__*/ StyledFactory("b");
export const __yak_base = /*#__PURE__*/ StyledFactory("base");
export const __yak_bdi = /*#__PURE__*/ StyledFactory("bdi");
export const __yak_bdo = /*#__PURE__*/ StyledFactory("bdo");
export const __yak_big = /*#__PURE__*/ StyledFactory("big");
export const __yak_blockquote = /*#__PURE__*/ StyledFactory("blockquote");
export const __yak_body = /*#__PURE__*/ StyledFactory("body");
export const __yak_br = /*#__PURE__*/ StyledFactory("br");
export const __yak_button = /*#__PURE__*/ StyledFactory("button");
export const __yak_canvas = /*#__PURE__*/ StyledFactory("canvas");
export const __yak_caption = /*#__PURE__*/ StyledFactory("caption");
export const __yak_cite = /*#__PURE__*/ StyledFactory("cite");
export const __yak_code = /*#__PURE__*/ StyledFactory("code");
export const __yak_col = /*#__PURE__*/ StyledFactory("col");
export const __yak_colgroup = /*#__PURE__*/ StyledFactory("colgroup");
export const __yak_data = /*#__PURE__*/ StyledFactory("data");
export const __yak_datalist = /*#__PURE__*/ StyledFactory("datalist");
export const __yak_dd = /*#__PURE__*/ StyledFactory("dd");
export const __yak_del = /*#__PURE__*/ StyledFactory("del");
export const __yak_details = /*#__PURE__*/ StyledFactory("details");
export const __yak_dfn = /*#__PURE__*/ StyledFactory("dfn");
export const __yak_dialog = /*#__PURE__*/ StyledFactory("dialog");
export const __yak_div = /*#__PURE__*/ StyledFactory("div");
export const __yak_dl = /*#__PURE__*/ StyledFactory("dl");
export const __yak_dt = /*#__PURE__*/ StyledFactory("dt");
export const __yak_em = /*#__PURE__*/ StyledFactory("em");
export const __yak_embed = /*#__PURE__*/ StyledFactory("embed");
export const __yak_fieldset = /*#__PURE__*/ StyledFactory("fieldset");
export const __yak_figcaption = /*#__PURE__*/ StyledFactory("figcaption");
export const __yak_figure = /*#__PURE__*/ StyledFactory("figure");
export const __yak_footer = /*#__PURE__*/ StyledFactory("footer");
export const __yak_form = /*#__PURE__*/ StyledFactory("form");
export const __yak_h1 = /*#__PURE__*/ StyledFactory("h1");
export const __yak_h2 = /*#__PURE__*/ StyledFactory("h2");
export const __yak_h3 = /*#__PURE__*/ StyledFactory("h3");
export const __yak_h4 = /*#__PURE__*/ StyledFactory("h4");
export const __yak_h5 = /*#__PURE__*/ StyledFactory("h5");
export const __yak_h6 = /*#__PURE__*/ StyledFactory("h6");
export const __yak_header = /*#__PURE__*/ StyledFactory("header");
export const __yak_hgroup = /*#__PURE__*/ StyledFactory("hgroup");
export const __yak_hr = /*#__PURE__*/ StyledFactory("hr");
export const __yak_html = /*#__PURE__*/ StyledFactory("html");
export const __yak_i = /*#__PURE__*/ StyledFactory("i");
export const __yak_iframe = /*#__PURE__*/ StyledFactory("iframe");
export const __yak_img = /*#__PURE__*/ StyledFactory("img");
export const __yak_input = /*#__PURE__*/ StyledFactory("input");
export const __yak_ins = /*#__PURE__*/ StyledFactory("ins");
export const __yak_kbd = /*#__PURE__*/ StyledFactory("kbd");
export const __yak_keygen = /*#__PURE__*/ StyledFactory("keygen");
export const __yak_label = /*#__PURE__*/ StyledFactory("label");
export const __yak_legend = /*#__PURE__*/ StyledFactory("legend");
export const __yak_li = /*#__PURE__*/ StyledFactory("li");
export const __yak_link = /*#__PURE__*/ StyledFactory("link");
export const __yak_main = /*#__PURE__*/ StyledFactory("main");
export const __yak_map = /*#__PURE__*/ StyledFactory("map");
export const __yak_mark = /*#__PURE__*/ StyledFactory("mark");
export const __yak_menu = /*#__PURE__*/ StyledFactory("menu");
export const __yak_menuitem = /*#__PURE__*/ StyledFactory("menuitem");
export const __yak_meta = /*#__PURE__*/ StyledFactory("meta");
export const __yak_meter = /*#__PURE__*/ StyledFactory("meter");
export const __yak_nav = /*#__PURE__*/ StyledFactory("nav");
export const __yak_noscript = /*#__PURE__*/ StyledFactory("noscript");
export const __yak_object = /*#__PURE__*/ StyledFactory("object");
export const __yak_ol = /*#__PURE__*/ StyledFactory("ol");
export const __yak_optgroup = /*#__PURE__*/ StyledFactory("optgroup");
export const __yak_option = /*#__PURE__*/ StyledFactory("option");
export const __yak_output = /*#__PURE__*/ StyledFactory("output");
export const __yak_p = /*#__PURE__*/ StyledFactory("p");
export const __yak_param = /*#__PURE__*/ StyledFactory("param");
export const __yak_picture = /*#__PURE__*/ StyledFactory("picture");
export const __yak_pre = /*#__PURE__*/ StyledFactory("pre");
export const __yak_progress = /*#__PURE__*/ StyledFactory("progress");
export const __yak_q = /*#__PURE__*/ StyledFactory("q");
export const __yak_rp = /*#__PURE__*/ StyledFactory("rp");
export const __yak_rt = /*#__PURE__*/ StyledFactory("rt");
export const __yak_ruby = /*#__PURE__*/ StyledFactory("ruby");
export const __yak_s = /*#__PURE__*/ StyledFactory("s");
export const __yak_samp = /*#__PURE__*/ StyledFactory("samp");
export const __yak_script = /*#__PURE__*/ StyledFactory("script");
export const __yak_section = /*#__PURE__*/ StyledFactory("section");
export const __yak_select = /*#__PURE__*/ StyledFactory("select");
export const __yak_small = /*#__PURE__*/ StyledFactory("small");
export const __yak_source = /*#__PURE__*/ StyledFactory("source");
export const __yak_span = /*#__PURE__*/ StyledFactory("span");
export const __yak_strong = /*#__PURE__*/ StyledFactory("strong");
export const __yak_style = /*#__PURE__*/ StyledFactory("style");
export const __yak_sub = /*#__PURE__*/ StyledFactory("sub");
export const __yak_summary = /*#__PURE__*/ StyledFactory("summary");
export const __yak_sup = /*#__PURE__*/ StyledFactory("sup");
export const __yak_table = /*#__PURE__*/ StyledFactory("table");
export const __yak_tbody = /*#__PURE__*/ StyledFactory("tbody");
export const __yak_td = /*#__PURE__*/ StyledFactory("td");
export const __yak_textarea = /*#__PURE__*/ StyledFactory("textarea");
export const __yak_tfoot = /*#__PURE__*/ StyledFactory("tfoot");
export const __yak_th = /*#__PURE__*/ StyledFactory("th");
export const __yak_thead = /*#__PURE__*/ StyledFactory("thead");
export const __yak_time = /*#__PURE__*/ StyledFactory("time");
export const __yak_tr = /*#__PURE__*/ StyledFactory("tr");
export const __yak_track = /*#__PURE__*/ StyledFactory("track");
export const __yak_u = /*#__PURE__*/ StyledFactory("u");
export const __yak_ul = /*#__PURE__*/ StyledFactory("ul");
export const __yak_use = /*#__PURE__*/ StyledFactory("use");
export const __yak_var = /*#__PURE__*/ StyledFactory("var");
export const __yak_video = /*#__PURE__*/ StyledFactory("video");
export const __yak_wbr = /*#__PURE__*/ StyledFactory("wbr");
export const __yak_circle = /*#__PURE__*/ StyledFactory("circle");
export const __yak_clipPath = /*#__PURE__*/ StyledFactory("clipPath");
export const __yak_defs = /*#__PURE__*/ StyledFactory("defs");
export const __yak_ellipse = /*#__PURE__*/ StyledFactory("ellipse");
export const __yak_foreignObject = /*#__PURE__*/ StyledFactory("foreignObject");
export const __yak_g = /*#__PURE__*/ StyledFactory("g");
export const __yak_image = /*#__PURE__*/ StyledFactory("image");
export const __yak_line = /*#__PURE__*/ StyledFactory("line");
export const __yak_linearGradient =
/*#__PURE__*/ StyledFactory("linearGradient");
export const __yak_marker = /*#__PURE__*/ StyledFactory("marker");
export const __yak_mask = /*#__PURE__*/ StyledFactory("mask");
export const __yak_path = /*#__PURE__*/ StyledFactory("path");
export const __yak_pattern = /*#__PURE__*/ StyledFactory("pattern");
export const __yak_polygon = /*#__PURE__*/ StyledFactory("polygon");
export const __yak_polyline = /*#__PURE__*/ StyledFactory("polyline");
export const __yak_radialGradient =
/*#__PURE__*/ StyledFactory("radialGradient");
export const __yak_rect = /*#__PURE__*/ StyledFactory("rect");
export const __yak_stop = /*#__PURE__*/ StyledFactory("stop");
export const __yak_svg = /*#__PURE__*/ StyledFactory("svg");
export const __yak_text = /*#__PURE__*/ StyledFactory("text");
export const __yak_tspan = /*#__PURE__*/ StyledFactory("tspan");
Loading