Skip to content

Instantly share code, notes, and snippets.

@frankyonnetti
Last active January 25, 2025 19:34
Show Gist options
  • Save frankyonnetti/1b49d77731b1154b4e3ce0f90d6ab5e9 to your computer and use it in GitHub Desktop.
Save frankyonnetti/1b49d77731b1154b4e3ce0f90d6ab5e9 to your computer and use it in GitHub Desktop.

Drupal theme using Vite contrib module

Basic theme dev setup for Vite after installing a Drupal Starterkit theme

Tested in Valet and MAMP Pro local environments.

themes/custom/THEME/package.json

{
  "name": "theme",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "sass": "^1.83.0",
    "vite": "^6.0.6"
  }
}

themes/custom/THEME/THEME.info.yml

# Disabled, using vite:true in libraries file instead.
# vite:
#   enableInAllLibraries: true
#   enableInAllComponents: true


# Includes library that points to vite (asset server) files.
libraries:
  - THEME/theme-style-script

# Require the Vite module.
dependencies:
  - 'vite:vite'

themes/custom/THEME/THEME.libraries.yml

# Libraries pointing to vite (asset server) during development
theme-style-script:
  vite:
    enabled: true
    manifest: assets/.vite/manifest.json
    baseUrl: '/themes/custom/THEME/assets/'
  css:
    theme:
      src/sass/style.scss: {}
  js:
    src/js/script.js: {}
  dependencies:
    - core/drupal
    - core/once

themes/custom/THEME/vite.config.js

import { defineConfig } from 'vite'
import path from 'path'
import fs from 'fs'
import os from 'os'
const homeDir = os.homedir()

export default defineConfig({
  build: {
    outDir: 'assets',
    emptyOutDir: true,
    manifest: true,
    sourcemap: true,
    cssMinify: false,
    rollupOptions: {
      // overwrite default .html entry
      input: [
        path.resolve(__dirname, './src/sass/style.scss'),
        path.resolve(__dirname, './src/js/script.js'),
      ],
      // Remove the [hash] from file name.
      output: {
        entryFileNames: `[name].js`,
        assetFileNames: `[name].[ext]`,
      }
    }
  },
  css: {
    devSourcemap: true,
    preprocessorOptions: {
      scss: {
        api: 'modern',
        quietDeps: true,
      },
    },
  },
  server: {
    host: "0.0.0.0",
    port: 5173,
    strictPort: true,
    origin: 'https://local.drupal10.test',
    https: {
      // provide path starting from home directory.
      key: fs.readFileSync(path.resolve(homeDir, 'PATH/TO/KEY')),
      cert: fs.readFileSync(path.resolve(homeDir, 'PATH/TO/CERT')),
    },
  },
})

sites/default/settings.local.php

/**
 * Vite settings.
 */
$settings['vite'] = [
  'devServerUrl' => 'https://local.drupal10.test:5173'
];

Initial Build

Once setup, run npm run build to build the dist/manifest.json and asset files. This will be used along with the Vite module when in production mode.

Then open in browser using local URL: e.g. https://local.drupal10.test

Drupal theme using ViteJS without the Vite contrib module

Basic theme dev setup for Vite after installing a Drupal Starterkit theme

Tested in Valet and MAMP Pro local environments.

themes/custom/THEME/package.json

{
  "name": "theme",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "sass": "^1.83.0",
    "vite": "^6.0.6"
  }
}

themes/custom/THEME/THEME.info.yml

# Do not include theme library files. They will be added within the THEME.theme file

libraries:
#  - THEME/theme-style-script

themes/custom/THEME/THEME.libraries.yml

theme-style-script:
  version: VERSION
  css:
    theme:
      dist/style.css: {}
  js:
    dist/script.js: {}
  dependencies:
    - core/drupal
    - core/once

# Libraries pointing to vite (asset server) during development
theme-style-script-dev:
  version: VERSION
  css:
    theme:
      https://local.drupal10.test:5173/src/sass/style.scss: {}
  js:
    https://local.drupal10.test:5173/@vite/client: { attributes: { type: module } }
    https://local.drupal10.test:5173/src/js/script.js: { attributes: { type: module } }
  dependencies:
    - core/drupal
    - core/once

themes/custom/THEME/THEME.theme

use Drupal\Core\Url;

/**
 * Implements hook_preprocess_HOOK() for page templates.
 */
function THEME_preprocess_page(&$variables) {
  // Check if Vite dev server is running.
  $vite_dev_server_url = 'https://local.drupal10.test:5173';
  $is_dev_mode = false;

  // Try to connect to the Vite dev server.
  try {
    $response = \Drupal::httpClient()->get($vite_dev_server_url);
    if ($response->getStatusCode() == 200) {
      $is_dev_mode = true;
    }
  }
  catch (\Exception $e) {
    // Dev server is not running.
  }

  // Attach the appropriate library.
  if ($is_dev_mode) {
    $variables['#attached']['library'][] = 'startervite/theme-style-script-dev';
  }
  else {
    $variables['#attached']['library'][] = 'startervite/theme-style-script';
  }
}

themes/custom/THEME/vite.config.js

import { defineConfig } from 'vite'
import path from 'path'
import fs from 'fs'
import os from 'os'
const homeDir = os.homedir()

export default defineConfig({
  build: {
    emptyOutDir: true,
    manifest: true,
    sourcemap: true,
    cssMinify: false,
    rollupOptions: {
      // overwrite default .html entry
      input: [
        path.resolve(__dirname, './src/sass/style.scss'),
        path.resolve(__dirname, './src/js/script.js'),
      ],
      // Remove the [hash] from file name.
      output: {
        entryFileNames: `[name].js`,
        assetFileNames: `[name].[ext]`,
      }
    }
  },
  css: {
    devSourcemap: true,
    preprocessorOptions: {
      scss: {
        api: 'modern',
        quietDeps: true,
      },
    },
  },
  server: {
    host: "0.0.0.0",
    port: 5173,
    strictPort: true,
    origin: 'https://local.drupal10.test',
    https: {
      // provide path starting from home directory.
      key: fs.readFileSync(path.resolve(homeDir, 'PATH/TO/KEY')),
      cert: fs.readFileSync(path.resolve(homeDir, 'PATH/TO/CERT')),
    },
  },
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment