In this article, I'll show you how to create a Svelte application with Nrwl NX and how install/configure Tailwind.
Tailwind is more popular than ever. If you've been following me, you know that I'm a huge fan. Recently I've started exploring Svelte, and wanted to know how to combine it with Tailwind. Not only that, but I also wanted to use Nrwl NX. This is a summary of my findings.
This is a short, but very practical article. If you hope to learn how Svelte/Tailwind work and why you should use those then this article is not for you.
Battleplan
First, we'll create a Nrwl NX workspace to structure our project.
Once we're done, we'll install the Svelte plugin into the workspace, and we'll use it to create our Svelte application.
Then, we'll install Tailwind, and a few supporting tools (e.g., PostCSS and autoprefixer). After that, we'll configure Tailwind, PostCSS, and our Svelte application. Finally, we'll load Tailwind's base styles in our application, and we'll add some styling.
Creating the Nx workspace
NX is a really powerful tool that I use in most of my projects. NX supports many frameworks and programming languages.
Creating an Nx workspace is as simple as running the following command:
npx create-nx-workspace <workspace name>
At the moment, NX does not natively support Svelte, so we need to create an empty workspace. The create-nx-workspace
command should generate the following structure for you:
This is the standard structure for Nx workspaces. The key elements are:
- The
apps
folder, which will later contain our Svelte application - The
libs
folder, which we can use to host parts of our monorepo to make those easily reusable across projects - The
nx.json
file, which is the configuration file of Nx - The
package.json
file in which we can manage our dependencies - The
workspace.json
file, which is the configuration file for our Nx workspace
Installing the Svelte plugin for Nx
Now that our workspace is created, we need to install the Svelte community plugin, created and maintained by Dominik Pieper. This plugin makes it possible to create and build Svelte applications in a Nrwl NX workspace. You can find the official documentation here.
For this example, I'll use npm
, but feel free to use yarn
if you prefer. Installing the plugin is quite straightforward:
npm install @nxext/svelte --save
Once done, we have access to the schematics and builders.
Creating the Svelte application
The Svelte plugin for NX includes a schematic that we will use to create our Svelte application:
npx nx g @nxext/svelte:app app_name
This command will generate the application and store it inside the apps/<app_name>
folder. Pick any name you fancy.
Inside that folder, you should find the following:
The code of the application can be found under src
, while the assets (e.g., images, fonts, global styles, etc) will go into the public
folder.
Notice the svelte.config.cjs
file. This is the configuration file for Svelte. We'll adapt it in a minute.
Svelte application configuration
In the previous section, I've mentioned the svelte.config.cjs
file that you should find under apps/<app name>
. Let's take a look at it:
All this file does is export a configuration object for the build of our Svelte application. By default, it uses the svelte-preprocess package, which is a preprocessor for Svelte providing support for PostCSS, SCSS, TypeScript, and much more.
The question is: how is that file used by the build system? To answer that question, we need to look at the workspace.json
file at the root of the NX workspace. It has been updated by the Svelte plugin for NX:
As you can see, the different targets (e.g., build and serve) use a specific executor: @nxext/svelte:build
, which is provided by the Svelte plugin for NX. That executor supports a number of options. In the example above, we care about the svelteConfig
setting, which defines the configuration file to use for Svelte.
When we build the Svelte application using NX, here's what happens:
- NX loads the
workspace.json
file to know about the different applications and libraries - It executes the requested operation (let's imagine a build of the Svelte app)
- When the Svelte app is being built, NX knows which executor to launch to take care of the grunt's work
- The Svelte NX plugin executor loads its configuration and notices the
svelteConfig
option. It loads the corresponding file (i.e.,svelte.config.cjs
), and updates its default build configuration accordingly
Installing Tailwind
To install Tailwind, we need to add a few packages to our project, as explained in the official documentation:
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
We'll also install a few additional ones:
npm install -D postcss-import@latest postcss-preset-env@latest node-sass@latest
Next up we'll configure Tailwind.
Configuring Tailwind
To configure Tailwind, create a file called tailwind.config.js
at the root of the NX workspace with the following contents:
This configuration enables the JIT mode of Tailwind and configures PurgeCSS properly. If you want to know more, check out the official documentation of Tailwind.
Now, we need to configure PostCSS.
Configuring PostCSS
PostCSS is a CSS processor that Tailwind relies on to do its magic.
The details about PostCSS are out of scope for this article, but let me explain something anyway. One thing you need to understand is that PostCSS can be used to define a processing pipeline for CSS code. The very first step of that pipeline receives the CSS as you wrote it, and processes it in some way. Then, the next step receives the result of the previous one and applies its own processing. And so on and so on. Now that you know this, you'll understand that the order of the elements in the configuration below does matter.
Go ahead and create a file called postcss.config.js
at the root of the NX workspace, with the following contents:
What does this do?
- First, we apply the
postcss-import
plugin, which adds support for the@import
syntax in our CSS code - Second, we enable Tailwind and its support for CSS nesting
- Third, we enable the
postcss-preset-env
plugin, which adds support for many other cool things
Alright, our CSS processing pipeline is configured!
Loading our PostCSS configuration
By default, the Svelte plugin for Nrwl NX uses its own Svelte preprocessing configuration. To make sure that our PostCSS configuration is loaded, we need to adapt the Svelte configuration file that we saw earlier.
Open up the svelte.config.cjs
file under apps/<app name>
and adapt it as follows:
As you can see, all we did was pass a configuration to the sveltePreprocess
method and define the postcss
configuration, associating it with an empty object. We only did this to replace the default postcss
configuration included by the Svelte NX plugin. This ensures that our own PostCSS configuration is loaded.
Load Tailwind in the Svelte application
We're almost ready to start using Tailwind in our code.
The next thing we need to do is load the default styles of Tailwind. To do so, go ahead and create a file called Tailwind.svelte
under apps/<app name>/src
, with the following contents:
There are a few things to notice here:
- We have marked the styles as
global
to make sure that those get applied on the global scope - We have set
lang="postcss"
to state that we're using PostCSS - We have loaded Tailwind's global styles using the
@tailwind
directive
Next, we need to load and use our Tailwind component inside the App
component. Open the src/<app name>/src/App.svelte
file and adapt the contents as follows:
What we did here is simply import the Tailwind.svelte
file, and use it.
We're done with the configuration! Great.
Running the application
To run the application, we can now use the following command:
npx nx serve <app_name>
I recommend getting used to the nx
command, which is the CLI of Nrxl NX.
If you're anything like me, then you might want to update the scripts
section of your package.json
file:
The names of the script should be self-descriptive. Just replace <app_name>
with the application name you've chosen.
To run our application, we can now use npm start
To learn more, make sure to look at the NX CLI documentation.
Alright, we can now start playing with Tailwind!
Using Tailwind
Let's look at a few ways we can use Tailwind in our Svelte application. Edit the App.svelte
file again as follows:
In this example, we've used Tailwind in three different ways:
- Inside the HTML template, we've used
class="..."
to modify the styles of an element using Tailwind. This is the approach you can find in most Tailwind examples out there - Inside the
style
tag, we've defined global styles by using the:global
scope supported by Svelte, and we've defined our styles using the@apply
directive - Inside the
style
tag, we've defined a class calledexample
, in which we've also used@apply
. This approach creates locally scoped styles that only exist for the current component.
If you look at the application now, it should look like this:
Template
If you're in a hurry, then you can use the template I've prepared and published on Github with the results of this experiment. You can find it here: https://github.com/dsebastien/svelte-tailwind-nx-template
Conclusion
In this article, I've explained how to create a Svelte application using Nrwl NX. I've also covered how to add Tailwind support. Hopefully, this will have taught you a few things about how to configure Svelte applications, PostCSS and Tailwind.
That’s it for today!
PS: check out the Dev Concepts collection of e-books, join the Software Crafters community, the Personal Knowledge Management community, and come say hi on Twitter!
Top comments (2)
Is it really worth all this setup process for NX? What does it do? Why would I use that?
Hello Denis,
I didn't cover the "why" in the article, but I'm a big fan of Nrwl NX. In a few words, to me NX brings the following key benefits:
And there's a ton more that I'm forgeting about.
Hope this helps!