Skip to content

Commit 523847d

Browse files
authored
Propper support for Uniwind pro (#8)
The recommended install method for uniwind pro, install aliasing, has a few weird quirks as `uniwind-pro` is still referenced in the node_modules directory (at least with pnpm). To handle this, the plugin needs to be updated to also handle `uniwind-pro` in any file path that it looks for `uniwind`.
1 parent 8142a3f commit 523847d

9 files changed

Lines changed: 68 additions & 78 deletions

File tree

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
[Uniwind](https://uniwind.dev/) config plugin for Next.js projects using Webpack. Turbopack-based projects are not supported at this stage.
44

5+
✅ Supports both Uniwind and Uniwind Pro
6+
57
## Example
68
See a fully working example project here: [Demo](http://uniwind-next.a16n.dev/) ([Source](https://github.com/a16n-dev/uniwind-plugin-next/tree/main/examples/next-16))
79

@@ -10,11 +12,11 @@ See the table below for tested versions of `uniwind-plugin-next` and correspondi
1012

1113
Tested on Next `16.1`, but other versions will likely work fine.
1214

13-
| Uniwind | uniwind-plugin-next |
14-
|-------------------|---------------------|
15-
| `1.2.7` | `1.4.0` |
16-
| `1.2.4` - `1.2.6` | `1.3.0` |
17-
| `1.2.2`-`1.2.3` | `1.2.0` |
15+
| Uniwind | Uniwind Pro | uniwind-plugin-next |
16+
|-------------------|----------------|---------------------|
17+
| `1.2.7` | `1.0.0-beta.9` | `1.4.2` |
18+
| `1.2.4` - `1.2.6` | N/A | `1.3.0` |
19+
| `1.2.2`-`1.2.3` | N/A | `1.2.0` |
1820

1921
## Installation & setup
2022
This setup guide assumes you already have a next.js project setup with Tailwind v4

packages/uniwind-plugin-next/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "uniwind-plugin-next",
3-
"version": "1.4.1",
3+
"version": "1.4.2",
44
"author": "Alexander Nicholson",
55
"description": "Compatibility plugin for using Uniwind with Next.js",
66
"homepage": "https://github.com/a16n-dev/uniwind-plugin-next#readme",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const UNIWIND_PACKAGE_NAME = "uniwind";
2+
export const UNIWIND_PRO_PACKAGE_NAME = "uniwind-pro";
Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
1-
import type { UniwindConfig } from "./common/types";
2-
import { withUniwindBase } from "./webpack/withUniwindBase";
3-
4-
export function withUniwind(
5-
nextConfig: any = {},
6-
uniwindConfig: UniwindConfig,
7-
): any {
8-
return withUniwindBase("uniwind", nextConfig, uniwindConfig);
9-
}
10-
11-
export function withUniwindPro(
12-
nextConfig: any = {},
13-
uniwindConfig: UniwindConfig,
14-
): any {
15-
return withUniwindBase("uniwind-pro", nextConfig, uniwindConfig);
16-
}
1+
export * from "./webpack/withUniwind";

packages/uniwind-plugin-next/src/webpack/UniwindWebpackPlugin.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { uniq } from "../common/util";
66
import { buildCSS } from "../uniwind/src/css";
77
import { buildDtsFile } from "../uniwind/src/utils/buildDtsFile";
88
import { stringifyThemes } from "../uniwind/src/utils/stringifyThemes";
9+
import {
10+
UNIWIND_PACKAGE_NAME,
11+
UNIWIND_PRO_PACKAGE_NAME,
12+
} from "../common/constants";
913

1014
const dirname =
1115
typeof __dirname !== "undefined" ? __dirname : import.meta.dirname;
@@ -16,14 +20,11 @@ export class UniwindWebpackPlugin {
1620
private readonly dtsFile: string;
1721
private readonly cssEntryFile: string;
1822

19-
constructor(
20-
private readonly packageName: uniwindPackageName,
21-
{
22-
cssEntryFile,
23-
extraThemes = [],
24-
dtsFile = "uniwind-types.d.ts",
25-
}: UniwindConfig,
26-
) {
23+
constructor({
24+
cssEntryFile,
25+
extraThemes = [],
26+
dtsFile = "uniwind-types.d.ts",
27+
}: UniwindConfig) {
2728
this.themes = uniq(["light", "dark", ...(extraThemes ?? [])]);
2829
this.dtsFile = dtsFile;
2930
this.cssEntryFile = cssEntryFile;
@@ -46,7 +47,7 @@ export class UniwindWebpackPlugin {
4647
const builtCSSPath = path.resolve(dirname, "../uniwind/uniwind.css");
4748
const targetCSSPath = path.join(
4849
path.dirname(
49-
require.resolve(this.packageName + "/package.json", {
50+
require.resolve(UNIWIND_PACKAGE_NAME + "/package.json", {
5051
paths: [compiler.context],
5152
}),
5253
),
@@ -61,7 +62,9 @@ export class UniwindWebpackPlugin {
6162
compiler.options.module = compiler.options.module || { rules: [] };
6263
compiler.options.module.rules.push({
6364
test: /config\.c?js$/,
64-
include: new RegExp(`${this.packageName}[\\/\\\\]dist`),
65+
include: new RegExp(
66+
`(${UNIWIND_PACKAGE_NAME}|${UNIWIND_PRO_PACKAGE_NAME})[\\/\\\\]dist`,
67+
),
6568
use: [
6669
{
6770
loader: path.resolve(dirname, "configInjectionLoader.js"),
@@ -76,7 +79,7 @@ export class UniwindWebpackPlugin {
7679
test: /\.js$/,
7780
exclude: /index\.js$/,
7881
include: new RegExp(
79-
`${this.packageName}[\\/\\\\]dist[\\/\\\\]module[\\/\\\\]components[\\/\\\\]web`,
82+
`(${UNIWIND_PACKAGE_NAME}|${UNIWIND_PRO_PACKAGE_NAME})[\\/\\\\]dist`,
8083
),
8184
use: [
8285
{

packages/uniwind-plugin-next/src/webpack/__tests__/UniwindWebpackPlugin.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ describe("UniwindWebpackPlugin", () => {
5050

5151
describe("constructor", () => {
5252
it("should initialize with default themes when no extraThemes provided", () => {
53-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
53+
const plugin = new UniwindWebpackPlugin({
5454
cssEntryFile: "uniwind.css",
5555
});
5656

5757
expect(plugin).toBeInstanceOf(UniwindWebpackPlugin);
5858
});
5959

6060
it("should merge extraThemes with default themes", () => {
61-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
61+
const plugin = new UniwindWebpackPlugin({
6262
cssEntryFile: "uniwind.css",
6363
extraThemes: ["brand", "custom"],
6464
});
@@ -67,7 +67,7 @@ describe("UniwindWebpackPlugin", () => {
6767
});
6868

6969
it("should deduplicate themes", () => {
70-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
70+
const plugin = new UniwindWebpackPlugin({
7171
cssEntryFile: "uniwind.css",
7272
extraThemes: ["light", "dark", "brand"],
7373
});
@@ -76,15 +76,15 @@ describe("UniwindWebpackPlugin", () => {
7676
});
7777

7878
it("should use default dtsFile when not provided", () => {
79-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
79+
const plugin = new UniwindWebpackPlugin({
8080
cssEntryFile: "uniwind.css",
8181
});
8282

8383
expect(plugin).toBeInstanceOf(UniwindWebpackPlugin);
8484
});
8585

8686
it("should use custom dtsFile when provided", () => {
87-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
87+
const plugin = new UniwindWebpackPlugin({
8888
cssEntryFile: "uniwind.css",
8989
dtsFile: "custom-types.d.ts",
9090
});
@@ -95,7 +95,7 @@ describe("UniwindWebpackPlugin", () => {
9595

9696
describe("apply", () => {
9797
it("should register beforeCompile hook", () => {
98-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
98+
const plugin = new UniwindWebpackPlugin({
9999
cssEntryFile: "uniwind.css",
100100
});
101101

@@ -114,7 +114,7 @@ describe("UniwindWebpackPlugin", () => {
114114
const { stringifyThemes } =
115115
await import("../../uniwind/src/utils/stringifyThemes");
116116

117-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
117+
const plugin = new UniwindWebpackPlugin({
118118
cssEntryFile: "uniwind.css",
119119
extraThemes: ["brand"],
120120
dtsFile: "types.d.ts",
@@ -137,7 +137,7 @@ describe("UniwindWebpackPlugin", () => {
137137
it("should only run once even if beforeCompile is called multiple times", async () => {
138138
const { buildCSS } = await import("../../uniwind/src/css");
139139

140-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
140+
const plugin = new UniwindWebpackPlugin({
141141
cssEntryFile: "uniwind.css",
142142
});
143143

@@ -151,7 +151,7 @@ describe("UniwindWebpackPlugin", () => {
151151
});
152152

153153
it("should add configInjectionLoader webpack rule", () => {
154-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
154+
const plugin = new UniwindWebpackPlugin({
155155
cssEntryFile: "uniwind.css",
156156
});
157157

@@ -178,7 +178,7 @@ describe("UniwindWebpackPlugin", () => {
178178
});
179179

180180
it("should add clientDirectiveLoader webpack rule", () => {
181-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
181+
const plugin = new UniwindWebpackPlugin({
182182
cssEntryFile: "uniwind.css",
183183
});
184184

@@ -207,7 +207,7 @@ describe("UniwindWebpackPlugin", () => {
207207
options: {},
208208
} as any;
209209

210-
const plugin = new UniwindWebpackPlugin(PACKAGE_NAME, {
210+
const plugin = new UniwindWebpackPlugin({
211211
cssEntryFile: "uniwind.css",
212212
});
213213

packages/uniwind-plugin-next/src/webpack/__tests__/withUniwind.test.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { describe, it, expect, vi, beforeEach } from "vitest";
2-
import { withUniwindBase } from "../withUniwindBase";
2+
import { withUniwind } from "../withUniwind";
33
import { UniwindWebpackPlugin } from "../UniwindWebpackPlugin";
44
import type { Configuration } from "webpack";
5-
import type { UniwindConfig } from "../types";
6-
7-
function withUniwind(nextConfig: any = {}, uniwindConfig: UniwindConfig): any {
8-
return withUniwindBase("uniwind", nextConfig, uniwindConfig);
9-
}
105

116
vi.mock("../UniwindWebpackPlugin", () => ({
127
UniwindWebpackPlugin: vi.fn().mockImplementation(function () {
@@ -63,7 +58,7 @@ describe("withUniwind", () => {
6358

6459
it("should deduplicate transpilePackages", () => {
6560
const nextConfig = {
66-
transpilePackages: ["uniwind", "react-native"],
61+
transpilePackages: ["uniwind", "uniwind-pro", "react-native"],
6762
};
6863

6964
const result = withUniwind(nextConfig, {
@@ -73,7 +68,11 @@ describe("withUniwind", () => {
7368
const uniwindCount = result.transpilePackages.filter(
7469
(p: string) => p === "uniwind",
7570
).length;
71+
const uniwindProCount = result.transpilePackages.filter(
72+
(p: string) => p === "uniwind-pro",
73+
).length;
7674
expect(uniwindCount).toBe(1);
75+
expect(uniwindProCount).toBe(1);
7776
});
7877

7978
it("should preserve other Next.js config properties", () => {
@@ -111,7 +110,7 @@ describe("withUniwind", () => {
111110

112111
const newConfig = result.webpack(webpackConfig, options);
113112

114-
expect(UniwindWebpackPlugin).toHaveBeenCalledWith("uniwind", {
113+
expect(UniwindWebpackPlugin).toHaveBeenCalledWith({
115114
cssEntryFile: "uniwind.css",
116115
});
117116
expect(newConfig.plugins).toHaveLength(3); // NormalModuleReplacementPlugin x 2 + UniwindWebpackPlugin
@@ -276,10 +275,7 @@ describe("withUniwind", () => {
276275

277276
result.webpack(webpackConfig, options);
278277

279-
expect(UniwindWebpackPlugin).toHaveBeenCalledWith(
280-
"uniwind",
281-
uniwindConfig,
282-
);
278+
expect(UniwindWebpackPlugin).toHaveBeenCalledWith(uniwindConfig);
283279
});
284280
});
285281
});

packages/uniwind-plugin-next/src/webpack/withUniwindBase.ts renamed to packages/uniwind-plugin-next/src/webpack/withUniwind.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import webpack from "webpack";
22
import type { Configuration } from "webpack";
3-
import path from "path";
43
import { UniwindWebpackPlugin } from "./UniwindWebpackPlugin";
5-
import { UniwindConfig, uniwindPackageName } from "../common/types";
4+
import { UniwindConfig } from "../common/types";
65
import { uniq } from "../common/util";
6+
import {
7+
UNIWIND_PACKAGE_NAME,
8+
UNIWIND_PRO_PACKAGE_NAME,
9+
} from "../common/constants";
710

811
const { NormalModuleReplacementPlugin } = webpack;
912

10-
export function withUniwindBase(
11-
packageName: uniwindPackageName,
13+
export function withUniwind(
1214
nextConfig: any = {},
1315
uniwindConfig: UniwindConfig,
1416
): any {
@@ -28,7 +30,8 @@ export function withUniwindBase(
2830
...nextConfig,
2931
transpilePackages: uniq([
3032
...(nextConfig.transpilePackages || []),
31-
packageName,
33+
UNIWIND_PACKAGE_NAME,
34+
UNIWIND_PRO_PACKAGE_NAME,
3235
"react-native",
3336
"react-native-web",
3437
]),
@@ -43,15 +46,14 @@ export function withUniwindBase(
4346
const context = resource.context || "";
4447

4548
if (
46-
context.includes(
47-
`${path.sep}${packageName}${path.sep}dist${path.sep}module${path.sep}components${path.sep}web`,
48-
)
49+
context.includes(`/${UNIWIND_PACKAGE_NAME}/dist`) ||
50+
context.includes(`/${UNIWIND_PRO_PACKAGE_NAME}/dist`)
4951
) {
5052
// Inside uniwind/dist → react-native-web
5153
resource.request = "react-native-web";
5254
} else {
5355
// Everywhere else → uniwind/web
54-
resource.request = `${packageName}/components/index`;
56+
resource.request = `${UNIWIND_PACKAGE_NAME}/components/index`;
5557
}
5658
}),
5759
);
@@ -65,13 +67,13 @@ export function withUniwindBase(
6567

6668
// Scope rewrite to react-native-web only
6769
if (context.includes("react-native-web/dist/exports/StyleSheet")) {
68-
resource.request = `${packageName}/components/createOrderedCSSStyleSheet`;
70+
resource.request = `${UNIWIND_PACKAGE_NAME}/components/createOrderedCSSStyleSheet`;
6971
}
7072
},
7173
),
7274
);
7375

74-
config.plugins.push(new UniwindWebpackPlugin(packageName, uniwindConfig));
76+
config.plugins.push(new UniwindWebpackPlugin(uniwindConfig));
7577

7678
// Execute the user-defined webpack config.
7779
if (typeof nextConfig.webpack === "function") {

0 commit comments

Comments
 (0)