Creación de un proyecto svelte + bulma + sass.
Tags: svelte, bulma, sass
Published: 2020-09-09 21:20:06

Durante las vacaciones de verano, descubrí **svelte**, un framework javascript que me ha parecido interesante, así que decidí realizar algunas pruebas de concepto. Una de ellas, era la integración con algún frameworks CSS popular y, ya puestos, que fuera personalizable con **sass**.

Buscando ejemplos y documentación, encontré alguna referencia al uso de **tailwindcss** y **bulma**, pero si bien describían como integrar el uso de sass, durante la fase de **build**, no se eliminaban los estilos css no utilizados, por lo que un **hola mundo**, con unas pocas clases css, acababa ocupndo más de **200KB**.

Pese a que dediqué algo de tiempo a la búsqueda, no encontré ningún ejemplo que lo hiciera, asi que me ha parecido que podría ser interesante compartir la solución que, tras varios intentos fallidos, me ha funcionado.

Asumiré que ya conoces **svelte** (si no es así, te aconsejo que visites su sitio web que está bastante bien documentado). Tampoco explicaré nada de **bulma** y **sass** (entre otras cosas, porque mis conocimientos brillan por su ausencia) así que me limitaré a enumerar brevemente los pasos necesarios para la configuración inicial mínima de un proyecto muy básico (como se puede observar en la imagen), pero que consigue el resultado perseguido, tener un esqueleto funcional con los 3 elementos integrados. 

![Hello World](https://dev-to-uploads.s3.amazonaws.com/i/tdorwsce49ffnchrp21v.png)

Lo primero que haremos es crear un nuevo proyecto **svelte** utitlizando el procedimiento habitual,y al que llamaremos **bulma-sass**.

```bash
npx degit sveltejs/template bulma-sass
cd bulma-sass/
```

Instalaremos las dependencias y módulos necesarios. 

```bash
npm install
npm install --save-dev bulma
npm install --save-dev node-sass
npm install --save-dev rollup-plugin-postcss 
npm install --save-dev @fullhuman/postcss-purgecss
```

Como no lo necesitaremos, borramos el contenido de **global.css** y **App.svelte**.

```bash
echo > ./public/global.css
echo > ./src/App.svelte
```
Nos aseguramos de que en la página **public/index.html** los enlaces sean relativos, en lugar de absolutos desde la raiz.

```html
	<link rel='stylesheet' href='global.css'>
	<link rel='stylesheet' href='build/bundle.css'>

    <script defer src='build/bundle.js'></script>
```

Creamos el fichero **src/mi-bulma.scss** para personalizar bulma a nuestro gusto y, como podéis comprobar, me he limitado a modificar las fuentes y el color primario, pero es suficiente para comprobar que el circuito funciona correctamente.

```scss
@charset "utf-8";

// Importamos fuentes de Google Font
@import url('https://fonts.googleapis.com/css?family=Nunito:100,200');

// Definimos nuestros colores
$color-primario: #990099;

// Actualizamos variables globales de Bulma
$family-sans-serif: "Nunito", sans-serif;
$primary: $color-primario;

// Importamos lo que necesitemos de Bulma.
@import "../node_modules/bulma/sass/utilities/_all.sass";
@import "../node_modules/bulma/sass/base/_all.sass";
@import "../node_modules/bulma/sass/components/_all.sass";
@import "../node_modules/bulma/sass/elements/_all.sass";
@import "../node_modules/bulma/sass/form/_all.sass";
@import "../node_modules/bulma/sass/grid/_all.sass";
@import "../node_modules/bulma/sass/layout/_all.sass";
@import "../node_modules/bulma/sass/helpers/_all.sass";
```

Ahora procedemos a modificar el fichero **rollup.config.js** generado por defecto, para que tenga el siguiente aspecto ```javascript
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';

// Añadidos a configuración por defecto para procesar Bulma scss
import postcss from 'rollup-plugin-postcss';                  // [+]
import Purgecss from "@fullhuman/postcss-purgecss";           // [+]

// Indicamos archivos a examinar para eliminar estilos no utilizados.
const purgeCss = Purgecss({                                   // [+]
	content: ["./src/**/*.svelte"],                           // [+]
	whitelist: ['body']                                       // [+]
});                                                           // [+] 

const production = !process.env.ROLLUP_WATCH;

function serve() {
	let server;
	
	function toExit() {
		if (server) server.kill(0);
	}

	return {
		writeBundle() {
			if (server) return;
			server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
				stdio: ['ignore', 'inherit', 'inherit'],
				shell: true
			});

			process.on('SIGTERM', toExit);
			process.on('exit', toExit);
		}
	};
}

export default {
	input: 'src/main.js',
	output: {
		sourcemap: true,
		format: 'iife',
		name: 'app',
		file: 'public/build/bundle.js'
	},
	plugins: [
		svelte({
			// enable run-time checks when not in production
			dev: !production,
			// we'll extract any component CSS out into
			// a separate file - better for performance
			css: css => {
				css.write('bundle.css');
			}
		}),

		// Plugin para postproceso de CSS
		postcss({                                             // [+]      
			plugins: [                                        // [+]
			  purgeCss                                        // [+]
			]                                                 // [+]
		}),                                                   // [+]
	  

		// If you have external dependencies installed from
		// npm, you'll most likely need these plugins. In
		// some cases you'll need additional configuration -
		// consult the documentation for details:
		// https://github.com/rollup/plugins/tree/master/packages/commonjs
		resolve({
			browser: true,
			dedupe: ['svelte']
		}),
		commonjs(),

		// In dev mode, call `npm run start` once
		// the bundle has been generated
		!production && serve(),

		// Watch the `public` directory and refresh the
		// browser on changes when not in production
		!production && livereload('public'),

		// If we're building for production (npm run build
		// instead of npm run dev), minify
		production && terser()
	],
	watch: {
		clearScreen: false
	}
};
```
He marcado las líneas añadidas con el comentario **// [+]**. No son muchas, pero son la clave de la solución.

Ya está todo preparado para que desarrollemos nuestra magnífica aplicación. Lo único que tenemos que hacer es importar nuestro fichero **src/mi-bulma.scss** en el fichero **src/App.svelte** para poder utilizar los estilos de bulma y dar rienda suelta a nuestra imaginación.

Os dejo, a modo de ejemplo, mi complicado desarrollo.

```javascript
<script>
     import './mi-bulma.scss';
</script>

<section class="section">
    <div class="container">
        <h1 class="title">
            <span style="color: blue">Hello</span> World
        </h1>
        <p class="subtitle" style="color: purple">
            Mi primer website con <strong>svelte + bulma + sass</strong>.
        </p>
        <p>
            <button class="button">
            Botón
            </button>
    
            <button class="button is-primary">
            Botón primario
            </button>
    
            <button class="button is-warning">
            Advertencia
            </button>
        </p>
    </div>
</section>
```

Ya sólo nos falta ejecutar
```bash
npm run build
```
**Et voilà !!!** en **8KB** tenemos empaquetada nuestra aplicación con todo lo necesario para funcionar.