next-yak
Version:
next-yak is a CSS-in-JS solution tailored for Next.js that seamlessly combines the expressive power of styled-components syntax with efficient build-time extraction of CSS using Next.js's built-in CSS configuration
125 lines (123 loc) • 4.51 kB
JavaScript
import { existsSync } from "node:fs";
import path, { dirname } from "node:path";
import { fileURLToPath } from "node:url";
//#region withYak/index.ts
const currentDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
const addYak = (yakOptions, nextConfig) => {
const minify = yakOptions.minify ?? process.env.NODE_ENV === "production";
const yakPluginOptions = {
minify,
basePath: currentDir,
prefix: yakOptions.prefix,
displayNames: yakOptions.displayNames ?? !minify,
suppressDeprecationWarnings: yakOptions.experiments?.suppressDeprecationWarnings ?? false,
reactRefreshReg: true
};
const transpilation = yakOptions.experiments?.transpilationMode ?? "CssModule";
const cssExtension = transpilation === "CssModule" ? ".yak.module.css" : ".yak.css";
if (process.env.TURBOPACK === "1" || process.env.TURBOPACK === "auto") addYakTurbopack(nextConfig, yakOptions, {
...yakPluginOptions,
importMode: {
value: "data:text/css;base64,",
transpilation: "Css",
encoding: "Base64"
}
});
else addYakWebpack(nextConfig, yakOptions, {
...yakPluginOptions,
importMode: {
value: `./{{__BASE_NAME__}}${cssExtension}!=!./{{__BASE_NAME__}}?./{{__BASE_NAME__}}${cssExtension}`,
transpilation,
encoding: "None"
}
});
return nextConfig;
};
function addYakTurbopack(nextConfig, yakOptions, yakPluginOptions) {
const yakLoader = removeUndefinedRecursive({
loader: path.join(currentDir, "../loaders/turbo-loader.cjs"),
options: {
yakOptions,
yakPluginOptions
}
});
nextConfig.turbopack ||= {};
nextConfig.turbopack.rules ||= {};
const ruleKey = "*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}";
const rule = {
loaders: [],
...nextConfig.turbopack.rules[ruleKey]
};
rule.loaders.push(yakLoader);
nextConfig.turbopack.rules[ruleKey] = rule;
const yakContext = resolveYakContext(yakOptions.contextPath, process.cwd());
if (yakContext) {
nextConfig.turbopack.resolveAlias ||= {};
nextConfig.turbopack.resolveAlias["next-yak/context/baseContext"] = `./${path.relative(process.cwd(), yakContext)}`;
}
}
function addYakWebpack(nextConfig, yakOptions, yakPluginOptions) {
nextConfig.experimental ||= {};
nextConfig.experimental.swcPlugins ||= [];
nextConfig.experimental.swcPlugins.push(["yak-swc", yakPluginOptions]);
const previousConfig = nextConfig.webpack;
nextConfig.webpack = (webpackConfig, options) => {
if (previousConfig) webpackConfig = previousConfig(webpackConfig, options);
webpackConfig.module.rules.push({
test: yakOptions.experiments?.transpilationMode === "Css" ? /\.yak\.css$/ : /\.yak\.module\.css$/,
loader: path.join(currentDir, "../loaders/webpack-loader.cjs"),
options: yakOptions
});
const yakContext = resolveYakContext(yakOptions.contextPath, webpackConfig.context || process.cwd());
if (yakContext) webpackConfig.resolve.alias["next-yak/context/baseContext"] = yakContext;
return webpackConfig;
};
}
function removeUndefinedRecursive(obj) {
if (typeof obj !== "object" || obj === null) return obj;
if (Array.isArray(obj)) {
const filtered = [];
for (let i = 0; i < obj.length; i++) {
const processed = removeUndefinedRecursive(obj[i]);
if (processed !== void 0) filtered.push(processed);
}
return filtered;
}
const newObj = {};
let hasChanges = false;
for (const key in obj) if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = removeUndefinedRecursive(obj[key]);
if (value !== void 0) {
newObj[key] = value;
hasChanges = true;
}
}
return hasChanges ? newObj : obj;
}
function resolveYakContext(contextPath, cwd) {
const yakContext = contextPath ? path.resolve(cwd, contextPath) : path.resolve(cwd, "yak.context");
const extensions = [
"",
".ts",
".tsx",
".js",
".jsx"
];
for (const extension in extensions) {
const fileName = yakContext + extensions[extension];
if (existsSync(fileName)) return fileName;
}
if (contextPath) throw new Error(`Could not find yak context file at ${yakContext}`);
}
const withYak = (maybeYakOptions, nextConfig) => {
if (nextConfig === void 0) return withYak({}, maybeYakOptions);
const yakOptions = maybeYakOptions;
if (typeof nextConfig === "function") return (...args) => {
const config = nextConfig(...args);
return config instanceof Promise ? config.then((config) => addYak(yakOptions, config)) : addYak(yakOptions, config);
};
return addYak(yakOptions, nextConfig);
};
//#endregion
export { resolveYakContext, withYak };
//# sourceMappingURL=index.js.map