3

In a NORMAL Svelte project (no SvelteKit) the static files are in the public directory and when running npm run build (rollup -c) the src folder is compiled into public/build and the public folder can then be hosted somewhere.

I now switched (an already existing) Svelte project to Vite and the static files are still under public but when running npm run build (vite build), everything is bundled into the dist directory. So all the files in the public directory are actually copied and exist twice in the project. Which means when changing or adding something (which doesn't effect the app logic) the project needs to be rebuild before it can be redeployed.

Can this be changed via the configuration, that either all compiled files are added again to the public directory or that the static files reside directly inside dist and nothing is copied during the build process?

Edit: The project should still be able to be run in dev mode npm run dev (vite) with the assets being served

Corrl
  • 6,206
  • 1
  • 10
  • 36

1 Answers1

3

Yes you can keep public files in dist without copying, but it's a little "hacking".

First you need to disable publicDir option to disable copying.

Then disable emptyOutdir to reserve files.

Finally you may want to clean old assets, so a buildStart hook is added, cleaning dist/assets when build starts.

The final vite.config.js (you may want to add some error handling):

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { rm } from 'fs/promises'

// https://vitejs.dev/config/
export default defineConfig(({ command }) => ({
  plugins: [
    svelte(),
    {
      buildStart() {
        if (command === 'build')
          rm('./dist/assets', { recursive: true }).catch(() => {})
      }
    },
  ],
  publicDir: false,
  build: {
    emptyOutDir: false,
  }
}))

Update: To serve those files in npm run dev, extra hacks are required. You need to create a custom server to achieve that. (Vite doesn't seem to provide a configuration approach.)

server.js:

import express from 'express'
import { createServer as createViteServer } from 'vite'

// Or use require if nodejs complains about ES module
// const express = require('express')
// const { createServer: createViteServer } = require('vite')

async function createServer() {
  const app = express()

  // Create Vite server in middleware mode.
  const vite = await createViteServer({
    server: { middlewareMode: 'html'},
  })

  // Do not serve built index.html when visiting http://localhost:3000/
  app.use(express.static('dist', { index: false }))

  // Use vite's connect instance as middleware
  app.use(vite.middlewares)

  app.listen(3000)
}

createServer()

And replace "dev": "vite" with "dev": "node server.js" in package.json

Allan Chain
  • 2,345
  • 1
  • 14
  • 29
  • Thanks for these settings! I think I missed a point in my question... the project should, besides being build and deployed, still be run in dev mode `npm run dev` (`vite`) with the assets being served. I think that's not possible like that, or am I wrong? – Corrl Mar 06 '22 at 21:41
  • @Corrl Yes, you are right. I have updated the answer (with even more hacks). – Allan Chain Mar 07 '22 at 00:41
  • So much hacks for such a seemingly simple setting... ;-) Thanks for the modification! You say replace `"serve": "vite"` - with the Svelte setup that's probably `dev` then. When doing that and run `npm run dev` with node v16 I get an error "Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension." which is gone by adding `"type": "module",` to `package.json` - then everything seems to work! This could/should be added to the answer? – Corrl Mar 08 '22 at 07:25
  • While running the `dev mode` worked fine, I now get an error when building "Rollup failed to resolve import "global.css" from *"index.html. This is most likely unintended because it can break your application at runtime. If you do want to externalize this module explicitly add it to`build.rollupOptions.external`"* (Silly me for not having tested that before....) I find for example this questions https://stackoverflow.com/questions/67696920/vite-rollup-failed-to-resolve-build-error but changing the path doesn't seem to help. Do you have an idea? – Corrl Mar 09 '22 at 07:31
  • @Corrl Seems that it's another problem which is not related to this question. Vite has changed a lot and the answers there don't work any more. There are some issues about this (like https://github.com/vitejs/vite/issues/5906). Currently I have no idea how to fix this. – Allan Chain Mar 09 '22 at 09:21
  • Thanks for the reply! So would you consider this as a bug and the build should usually work with your settings? – Corrl Mar 09 '22 at 11:21
  • 1
    @Corrl Yes, it's vite's fault. Vite considered your `global.css` as a css module just because it can't be found in `src` or `public`. But it's actually not. – Allan Chain Mar 09 '22 at 14:32
  • I've been in these types of situations before not just with Vite, but also Rollup (i.e., where the LOE / hacking required to achieve some simple file shuffling was not worth it), so in the end I create a `build.sh` shell script and use good ol' `cp/mv` to do whatever needed to be done. – thdoan Dec 16 '22 at 00:07