Skip to content

Commit

Permalink
feat(tailwind-adapter): add 'embedded' configurable (#652)
Browse files Browse the repository at this point in the history
* feat(tailwind-adapter): add 'embedded' configurable

* chore(www): update content
  • Loading branch information
aralroca authored Nov 29, 2024
1 parent f4f6446 commit d8d1dad
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 6 deletions.
28 changes: 28 additions & 0 deletions docs/building-your-application/integrations/tailwind-css.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,34 @@ And you are ready to use TailwindCSS in your Brisa project.
>
> Installing the dependencies manually, take care to use a TailwindCSS version `v.4.x`.
## Configuration

You can configure TailwindCSS in your `brisa.config.ts` file:

```ts
import brisaTailwindCSS from "brisa-tailwindcss";

export default {
integrations: [brisaTailwindCSS({ embedded: false })],
} satisfies Configuration;
```

The current configuration has only one option:

- `embedded` (optional): If you want to embed the TailwindCSS CSS in the build output. Default is `true`.

> [!NOTE]
>
> Tailwind needs a subdependency that cannot be compiled, which is [lightningcss](https://github.com/parcel-bundler/lightningcss), so the default is to treat it as external and then embed it inside build.
### Type

```ts
type Config = {
embedded?: boolean;
};
```

## Defaults

If you don't have any `.css` file with `@tailwind` directive or `tailwindcss` import, Brisa will automatically generate in build-time a default CSS file with TailwindCSS directives to be similar than [TailwindCSS CDN](https://tailwindcss.com/docs/installation/play-cdn):
Expand Down
6 changes: 5 additions & 1 deletion packages/brisa-tailwindcss/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
type Config = {
embedded?: boolean;
};

/**
* To properly integrate TailwindCSS, you have to add the following code to
* your `brisa.config.ts` file:
Expand All @@ -12,7 +16,7 @@
*
* - [Docs](https://brisa.build/building-your-application/integrations/tailwind-css#integrating-tailwind-css)
*/
export default function tailwindCSS(): {
export default function tailwindCSS(config?: Config): {
name: string;
transpileCSS(pathname: string, content: string): Promise<string>;
defaultCSS: {
Expand Down
22 changes: 19 additions & 3 deletions packages/brisa-tailwindcss/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { describe, expect, it, spyOn } from 'bun:test';
import fs from 'node:fs/promises';
import packageJSON from './package.json';
import libs from './libs.json';
import brisaTailwindcss from '.';

const TAILWIND_VERSION = packageJSON.devDependencies.tailwindcss;

describe('brisa-tailwindcss', () => {
it('should return the correct name', () => {
const integration = brisaTailwindcss();
Expand Down Expand Up @@ -112,4 +109,23 @@ describe('brisa-tailwindcss', () => {
mockCp.mockRestore();
mockExists.mockRestore();
});

it('should not embed tailwindcss when embedded is false', async () => {
const integration = brisaTailwindcss({ embedded: false });
const mockLog = spyOn(console, 'log');
const mockCp = spyOn(fs, 'cp').mockResolvedValue();
const mockExists = spyOn(fs, 'exists').mockResolvedValue(true);

await integration.afterBuild({
BUILD_DIR: import.meta.dirname,
LOG_PREFIX: { INFO: 'INFO', WAIT: 'WAIT', TICK: 'TICK' },
});

expect(mockLog).not.toHaveBeenCalled();
expect(mockCp).not.toHaveBeenCalled();
expect(mockExists).not.toHaveBeenCalled();
mockLog.mockRestore();
mockCp.mockRestore();
mockExists.mockRestore();
});
});
5 changes: 4 additions & 1 deletion packages/brisa-tailwindcss/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import fs from 'node:fs/promises';
import path from 'node:path';
import libs from './libs.json';

const defaultConfig = { embedded: true };

// Note: is not bundled here to avoid issues with lightningcss
export default function brisaTailwindcss() {
export default function brisaTailwindcss({ embedded = true } = defaultConfig) {
return {
name: 'brisa-tailwindcss',
async transpileCSS(pathname: string, content: string) {
Expand All @@ -30,6 +32,7 @@ export default function brisaTailwindcss() {
// work correctly. As a solution, we install tailwind in the build folder and in this way the problem is solved.
// Issue: https://github.com/brisa-build/brisa/issues/637
async afterBuild({ BUILD_DIR, LOG_PREFIX }) {
if (!embedded) return;
const start = Date.now();
const destNodeModules = path.join(BUILD_DIR, 'node_modules');
const nodeModules = Bun.resolveSync('brisa', BUILD_DIR).split('brisa')[0];
Expand Down
19 changes: 18 additions & 1 deletion packages/www/src/public/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -4049,7 +4049,7 @@
{
"id": "/building-your-application/deploying/docker#containerize-with-docker",
"title": "Containerize with Docker",
"text": "This guide assumes you already have Docker Desktop installed. Docker is a platform for packaging and running an application as a lightweight, portable container that encapsulates all the necessary dependencies. To containerize our application, we define a Dockerfile. This file contains a list of instructions to initialize the container, copy our local project files into it, install dependencies, and start the application. # Adjust BUN_VERSION as desired\nARG BUN_VERSION=1.1.34\nFROM oven/bun:${BUN_VERSION}-slim AS base\n\n# Brisa app lives here\nWORKDIR /app\n\n# Set production environment\nENV NODE_ENV=\"production\"\n\n# Throw-away build stage to reduce the size of the final image\nFROM base AS build\n\n# Install node modules\nCOPY --link bun.lockb package.json ./\nRUN bun install --ci\n\n# Copy Brisa application code\nCOPY --link . .\n\n# Build Brisa application\nRUN bun run build\n\n# Final stage for app image\nFROM base\n\n# Copy built Brisa application\nCOPY --from=build /app /app\n\n# Start the Brisa server on port 3000\nEXPOSE 3000\nCMD [ \"bun\", \"run\", \"start\" ] Now that you have your docker image, let's look at .dockerignore which has the same syntax as .gitignore; here, you need to specify the files/directories that must not go in any stage of the docker build. An example of a ignore file is: dockerignore: .vscode\nnode_modules\n.DS_Store\nbuild If you want to be more strict, you can also invert the .dockerignore and use it as an allowed file. An example of how this would work is: dockerignore: # Ignore all files from your repo\n*\n\n# Allow specific files or folders\n!bun.lockb\n!package.json\n!src Making the .dockerignore an allowed file becomes very handy to prevent trash on your image, or sensitive information. For example secrets, coverage files or another dev on your team using a different IDE. We'll now use docker build to convert this Dockerfile into a Docker image. The result will be a self-contained template containing all the dependencies and configurations required to run the application on any platform. docker build -t my-app . The -t flag lets us specify a name for the image. We've built a new Docker image. Now let's use that image to spin up an actual, running container. docker run -p 3000:3000 my-app We'll use docker run to start a new container using the my-app image. We'll map the container's port 3000 to our local machine's port 3000 (-p 3000:3000). The run command prints a string representing the container ID. The container is now running in the background. Visit localhost:3000. You should see your homepage. Optional: the flag -d flag to run in detached mode to run the container in the background. To stop the container, we'll use docker stop <container-id>. If you can't find the container ID, you can use docker ps to list all running containers. That's it! Refer to the Docker documentation for more advanced usage.",
"text": "This guide assumes you already have Docker Desktop installed. Docker is a platform for packaging and running an application as a lightweight, portable container that encapsulates all the necessary dependencies. To containerize our application, we define a Dockerfile. This file contains a list of instructions to initialize the container, copy our local project files into it, install dependencies, and start the application. # Adjust BUN_VERSION as desired\nARG BUN_VERSION=1.1.38\nFROM oven/bun:${BUN_VERSION}-slim AS base\n\n# Brisa app lives here\nWORKDIR /app\n\n# Set production environment\nENV NODE_ENV=\"production\"\n\n# Throw-away build stage to reduce the size of the final image\nFROM base AS build\n\n# Install node modules\nCOPY --link bun.lockb package.json ./\nRUN bun install --ci\n\n# Copy Brisa application code\nCOPY --link . .\n\n# Build Brisa application\nRUN bun run build\n\n# Final stage for app image\nFROM base\n\n# Copy built Brisa application\nCOPY --from=build /app /app\n\n# Start the Brisa server on port 3000\nEXPOSE 3000\nCMD [ \"bun\", \"run\", \"start\" ] Now that you have your docker image, let's look at .dockerignore which has the same syntax as .gitignore; here, you need to specify the files/directories that must not go in any stage of the docker build. An example of a ignore file is: dockerignore: .vscode\nnode_modules\n.DS_Store\nbuild If you want to be more strict, you can also invert the .dockerignore and use it as an allowed file. An example of how this would work is: dockerignore: # Ignore all files from your repo\n*\n\n# Allow specific files or folders\n!bun.lockb\n!package.json\n!src Making the .dockerignore an allowed file becomes very handy to prevent trash on your image, or sensitive information. For example secrets, coverage files or another dev on your team using a different IDE. We'll now use docker build to convert this Dockerfile into a Docker image. The result will be a self-contained template containing all the dependencies and configurations required to run the application on any platform. docker build -t my-app . The -t flag lets us specify a name for the image. We've built a new Docker image. Now let's use that image to spin up an actual, running container. docker run -p 3000:3000 my-app We'll use docker run to start a new container using the my-app image. We'll map the container's port 3000 to our local machine's port 3000 (-p 3000:3000). The run command prints a string representing the container ID. The container is now running in the background. Visit localhost:3000. You should see your homepage. Optional: the flag -d flag to run in detached mode to run the container in the background. To stop the container, we'll use docker stop <container-id>. If you can't find the container ID, you can use docker ps to list all running containers. That's it! Refer to the Docker documentation for more advanced usage.",
"titles": [
"Docker"
]
Expand Down Expand Up @@ -4275,6 +4275,23 @@
"Integrating Tailwind CSS v4"
]
},
{
"id": "/building-your-application/integrations/tailwind-css#configuration",
"title": "Configuration",
"text": "You can configure TailwindCSS in your brisa.config.ts file: import brisaTailwindCSS from \"brisa-tailwindcss\";\n\nexport default {\n integrations: [brisaTailwindCSS({ embedded: false })],\n} satisfies Configuration; The current configuration has only one option: embedded (optional): If you want to embed the TailwindCSS CSS in the build output. Default is true. Tailwind needs a subdependency that cannot be compiled, which is lightningcss, so the default is to treat it as external and then embed it inside build.",
"titles": [
"Integrating Tailwind CSS v4"
]
},
{
"id": "/building-your-application/integrations/tailwind-css#type",
"title": "Type",
"text": "type Config = {\n embedded?: boolean;\n};",
"titles": [
"Integrating Tailwind CSS v4",
"Configuration"
]
},
{
"id": "/building-your-application/integrations/tailwind-css#defaults",
"title": "Defaults",
Expand Down

0 comments on commit d8d1dad

Please sign in to comment.