Skip to main content Skip to docs navigation

Bootstrap y Webpack

La guía oficial sobre cómo incluir y empaquetar el CSS y JavaScript de Bootstrap en tu proyecto usando Webpack.

¿Quieres ir directamente al final? Descarga el código fuente y la demostración de trabajo para esta guía desde el repositorio twbs/examples. También puedes abrir el ejemplo en StackBlitz para edición en vivo.

¿Qué es Webpack?

Webpack es un empaquetador de módulos de JavaScript que procesa módulos y sus dependencias para generar activos estáticos. Simplifica la administración de aplicaciones web complejas con múltiples archivos y dependencias.

Configuración

Estamos creando un proyecto Webpack con Bootstrap desde cero, por lo que existen algunos prerrequisitos y pasos previos antes de que podamos comenzar. Esta guía requiere que tengas instalado Node.js y cierta familiaridad con la terminal.

  1. Crea una carpeta de proyecto y configura npm. Crearemos la carpeta my-project e inicializaremos npm con el argumento -y para evitar que nos haga todas las preguntas interactivas.

    mkdir my-project && cd my-project
    npm init -y
    
  2. Instala Webpack. A continuación, necesitamos instalar nuestras dependencias de desarrollo de Webpack: webpack para el núcleo de Webpack, webpack-cli para que podamos ejecutar comandos de Webpack desde la terminal y webpack-dev-server para que podamos ejecutar un servidor de desarrollo local. Además, instalaremos html-webpack-plugin para poder almacenar nuestro index.html en el directorio src en lugar del directorio predeterminado dist. Usamos --save-dev para indicar que estas dependencias son solo para uso de desarrollo y no para producción.

    npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
    
  3. Instala Bootstrap. Ahora podemos instalar Bootstrap. También instalaremos Popper ya que nuestros menús desplegables, popovers y tooltips dependen de él para su posicionamiento. Si no planeas usar esos componentes, puedes omitir Popper aquí.

    npm i --save bootstrap @popperjs/core
    
  4. Instala dependencias adicionales. Además de Webpack y Bootstrap, necesitamos algunas dependencias más para importar y empaquetar correctamente el CSS y JS de Bootstrap con Webpack. Estas incluyen Sass, algunos cargadores (loaders) y Autoprefixer.

    npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader
    

Ahora que tenemos todas las dependencias necesarias instaladas, podemos ponernos a trabajar en la creación de los archivos del proyecto e importando Bootstrap.

Estructura del proyecto

Ya hemos creado la carpeta my-project e inicializado npm. Ahora también crearemos nuestras carpetas src y dist para completar la estructura del proyecto. Ejecuta lo siguiente desde my-project, o crea manualmente la estructura de carpetas y archivos que se muestra a continuación.

mkdir {src,src/js,src/scss}
touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js

Cuando hayas terminado, tu proyecto completo debería verse así:

my-project/
├── src/
│   ├── js/
│   │   └── main.js
│   ├── scss/
│   │   └── styles.scss
│   └── index.html
├── package-lock.json
├── package.json
└── webpack.config.js

En este punto, todo está en el lugar correcto, pero Webpack no funcionará porque aún no hemos completado nuestro webpack.config.js.

Configurar Webpack

Con las dependencias instaladas y nuestra carpeta de proyecto lista para que comencemos a programar, ahora podemos configurar Webpack y ejecutar nuestro proyecto localmente.

  1. Abre webpack.config.js en tu editor. Dado que está en blanco, necesitaremos agregarle una configuración básica para poder iniciar nuestro servidor. Esta parte de la configuración le dice a Webpack dónde buscar el JavaScript de nuestro proyecto, dónde enviar el código compilado (dist) y cómo debe comportarse el servidor de desarrollo (extrayendo de la carpeta dist con recarga en caliente).

    'use strict'
    
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ]
    }
    
  2. A continuación, completamos nuestro src/index.html. Esta es la página HTML que Webpack cargará en el navegador para utilizar el CSS y JS empaquetados que le agregaremos en pasos posteriores. Antes de poder hacer eso, tenemos que darle algo que renderizar e incluir el JS de salida (output) del paso anterior.

    <!doctype html>
    <html lang="es">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrap con Webpack</title>
      </head>
      <body>
        <div class="container py-4 px-3 mx-auto">
          <h1>¡Hola, Bootstrap y Webpack!</h1>
          <button class="btn btn-primary">Botón primario</button>
        </div>
      </body>
    </html>
    

    Estamos incluyendo un poco de estilo de Bootstrap aquí con el div class="container" y el <button> para que podamos ver cuándo Webpack carga el CSS de Bootstrap.

  3. Ahora necesitamos un script npm para ejecutar Webpack. Abre package.json y agrega el script start que se muestra a continuación (ya deberías tener el script de prueba). Usaremos este script para iniciar nuestro servidor local de desarrollo de Webpack. También puedes agregar un script build como se muestra a continuación para compilar tu proyecto.

    {
      // ...
      "scripts": {
        "start": "webpack serve",
        "build": "webpack build --mode=production",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      // ...
    }
    
  4. Y finalmente, podemos iniciar Webpack. Desde la carpeta my-project en tu terminal, ejecuta ese script npm recién agregado:

    npm start
    
    Servidor de desarrollo Webpack en ejecución

En la siguiente y última sección de esta guía, configuraremos los cargadores (loaders) de Webpack e importaremos todo el CSS y JavaScript de Bootstrap.

Importar Bootstrap

La importación de Bootstrap en Webpack requiere los cargadores (loaders) que instalamos en la primera sección. Los hemos instalado con npm, pero ahora Webpack debe configurarse para usarlos.

  1. Configura los cargadores (loaders) en webpack.config.js. Tu archivo de configuración ahora está completo y debería coincidir con el fragmento a continuación. La única parte nueva aquí es la sección module.

    'use strict'
    
    const path = require('path')
    const autoprefixer = require('autoprefixer')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ],
      module: {
        rules: [
          {
            test: /\.(scss)$/,
            use: [
              {
                // Agrega CSS al DOM inyectando una etiqueta `<style>`
                loader: 'style-loader'
              },
              {
                // Interpreta `@import` y `url()` como `import/require()` y los resolverá
                loader: 'css-loader'
              },
              {
                // Cargador para que webpack procese CSS con PostCSS
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      autoprefixer
                    ]
                  }
                }
              },
              {
                // Carga un archivo SASS/SCSS y lo compila a CSS
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    // Opcional: Silenciar las advertencias de desaprobación de Sass. Consulta la nota a continuación.
                    silenceDeprecations: [
                      'mixed-decls',
                      'color-functions',
                      'global-builtin',
                      'import'
                    ]
                  }
                }
              }
            ]
          }
        ]
      }
    }
    

    Aquí tienes un resumen de por qué necesitamos todos estos cargadores. style-loader inyecta el CSS en un elemento <style> en el <head> de la página HTML, css-loader ayuda a utilizar @import y url(), postcss-loader es necesario para Autoprefixer y sass-loader nos permite usar Sass.

    Nota: Las advertencias de desaprobación de Sass se muestran al compilar archivos Sass de origen con las últimas versiones de Dart Sass. Esto no impide la compilación ni el uso de Bootstrap. Estamos trabajando en una solución a largo plazo, pero mientras tanto, estas advertencias de desaprobación se pueden ignorar.

  2. Ahora, importemos el CSS de Bootstrap. Agrega lo siguiente a src/scss/styles.scss para importar todo el Sass de origen de Bootstrap.

    // Importar todo el CSS de Bootstrap
    @import "bootstrap/scss/bootstrap";
    

    También puedes importar nuestras hojas de estilo individualmente si lo deseas. Lee nuestra documentación de importación de Sass para más detalles.

  3. A continuación, cargamos el CSS e importamos el JavaScript de Bootstrap. Agrega lo siguiente a src/js/main.js para cargar el CSS e importar todo el JS de Bootstrap. Popper se importará automáticamente a través de Bootstrap.

    // Importar nuestro CSS personalizado
    import '../scss/styles.scss'
    
    // Importar todo el JS de Bootstrap
    import * as bootstrap from 'bootstrap'
    

    También puedes importar plugins de JavaScript individualmente según sea necesario para mantener reducido el tamaño de los paquetes:

    import Alert from 'bootstrap/js/dist/alert'
    
    // o bien, especifica qué plugins necesitas:
    import { Tooltip, Toast, Popover } from 'bootstrap'
    

    Lee nuestra documentación de JavaScript para obtener más información sobre cómo usar los plugins de Bootstrap.

  4. ¡Y listo! 🎉 Con el Sass y JS fuente de Bootstrap completamente cargados, tu servidor de desarrollo local ahora debería verse así:

    Servidor de desarrollo Webpack ejecutándose con Bootstrap

    Ahora puedes comenzar a agregar los componentes de Bootstrap que quieras usar. Asegúrate de consultar el proyecto de ejemplo de Webpack completo para saber cómo incluir Sass personalizado adicional y optimizar tu compilación importando solo las partes del CSS y JS de Bootstrap que necesites.

Optimizaciones de producción

Dependiendo de tu configuración, es posible que desees implementar algunas optimizaciones adicionales de seguridad y velocidad útiles para ejecutar el proyecto en producción. Ten en cuenta que estas optimizaciones no se aplican en el proyecto de ejemplo de Webpack y depende de ti implementarlas.

Extracción de CSS

El style-loader que configuramos anteriormente emite convenientemente el CSS en el paquete de modo que no es necesario cargar manualmente un archivo CSS en dist/index.html. Sin embargo, es posible que este enfoque no funcione con una Política de seguridad de contenido (CSP) estricta y puede convertirse en un cuello de botella en tu aplicación debido al gran tamaño del paquete.

Para separar el CSS de modo que podamos cargarlo directamente desde dist/index.html, usa el plugin de Webpack mini-css-extract-loader.

Primero, instala el plugin:

npm install --save-dev mini-css-extract-plugin

Luego crea la instancia y usa el plugin en la configuración de Webpack:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,6 +3,7 @@
 const path = require('path')
 const autoprefixer = require('autoprefixer')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
+const miniCssExtractPlugin = require('mini-css-extract-plugin')
 
 module.exports = {
   mode: 'development',
@@ -17,7 +18,8 @@ module.exports = {
     hot: true
   },
   plugins: [
-    new HtmlWebpackPlugin({ template: './src/index.html' })
+    new HtmlWebpackPlugin({ template: './src/index.html' }),
+    new miniCssExtractPlugin()
   ],
   module: {
     rules: [
@@ -25,8 +27,8 @@ module.exports = {
         test: /\.(scss)$/,
         use: [
           {
-            // Adds CSS to the DOM by injecting a `<style>` tag
-            // loader: 'style-loader'
+            // Extracts CSS for each JS file that includes CSS
+            loader: miniCssExtractPlugin.loader
           },
           {

Después de ejecutar npm run build nuevamente, habrá un nuevo archivo dist/main.css, que contendrá todo el CSS importado por src/js/main.js. Si ves dist/index.html en tu navegador ahora, faltará el estilo, ya que ahora está en dist/main.css. Puedes incluir el CSS generado en dist/index.html de esta manera:

--- a/dist/index.html
+++ b/dist/index.html
@@ -3,6 +3,7 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="./main.css">
     <title>Bootstrap w/ Webpack</title>
   </head>
   <body>

Extracción de archivos SVG

El CSS de Bootstrap incluye múltiples referencias a archivos SVG a través de URI data: en línea. Si defines una Política de seguridad de contenido para tu proyecto que bloquea las URI data: para imágenes, estos archivos SVG no se cargarán. Puedes solucionar este problema extrayendo los archivos SVG en línea utilizando la función de módulos de activos (asset modules) de Webpack.

Configura Webpack para extraer archivos SVG en línea así:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,6 +23,14 @@ module.exports = {
   },
   module: {
     rules: [
+      {
+        mimetype: 'image/svg+xml',
+        scheme: 'data',
+        type: 'asset/resource',
+        generator: {
+          filename: 'icons/[hash].svg'
+        }
+      },
       {
         test: /\.(scss)$/,
         use: [

Después de ejecutar npm run build nuevamente, encontrarás los archivos SVG extraídos en dist/icons y referenciados correctamente desde el CSS.


¿Ves algo incorrecto o desactualizado aquí? Por favor, abre un issue en GitHub. ¿Necesitas ayuda para solucionar problemas? Busca o inicia una discusión en GitHub.