carbon-design-system / carbon-preprocess-svelte

Svelte preprocessors for the Carbon Design System
Apache License 2.0
68 stars 6 forks source link

Run optimizeImports for all imports on dev server start #41

Closed Addeuz closed 5 months ago

Addeuz commented 1 year ago

Hello, when I do npm install in my project to install a new dependency or update another dependency the .vite/deps/ folder gets deleted. It then gets added when I run npm run dev again.

The problem I now get with optimizeImports() is that it only optimizes the imports when I go to the SvelteKit route that has the import. The issue I'm now facing is that the request to fetch the optimized imports fails because of a timeout: Screenshot from 2022-11-16 13-15-05

And because it fails I get redirected back to the route I came from. Then when I try to go to the route again it works because now they have been optimized. Screenshot from 2022-11-16 13-15-56

It feels like the optimization of the import isn't fast enough for SvelteKit to get the optimized version in .vite/deps and therefore times out.

Do I miss some setting in my svelte/vite config? (See them below)

And is it at all possible to optimize all imports (if we have to) when we start the dev server?

I would also like to add that I had no issue with this when I ran SvelteKit version 405 (very old version without the new routing stuff). But updating to the latest version gave me this issue.

// svelte.config.js
import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-static';
import { optimizeImports } from 'carbon-preprocess-svelte';

const config = {
  preprocess: [
    preprocess({
      scss: {
        includePaths: ['./src/styles/'],
        data: '@import "index.scss;"'
      }
    }),
    optimizeImports()
  ],
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: '404.html'
    })
  },
  ...
};
// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import { resolve } from 'path';
import wasmPack from 'vite-plugin-wasm-pack';

const config = {
  define: {
    'process.env': process.env
  },
  resolve: {
    alias: {
      $components: resolve('./src/components'),
      $stores: resolve('./src/stores'),
      $types: resolve('./src/types')
    }
  },
  plugins: [sveltekit(), wasmPack('./sie-parser-wasm')],
  ssr: {
    noExternal: ['@df/common']
  },
  server: {
    port: 3000,
    strictPort: true
  }
};
metonym commented 1 year ago

Note that optimizeImports is a Svelte preprocessor, so it runs at compile time (i.e., every time you update a source file).

It might be worth first trying to explicitly instruct Vite to not optimize carbon-components-svelte:

optimizeDeps: {
  exclude: ['carbon-components-svelte']
}

However, it sounds like you want the experimental Svelte Vite plugin feature that prebundles the entire library ahead of time. This may cause a longer cold start but will probably resolve your issue. See their example config.

// vite.config.js
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { defineConfig } from 'vite';

export default defineConfig({
    plugins: [svelte({ prebundleSvelteLibraries: true })],
    optimizeDeps: {
        // carbon-components-svelte is large, prebundle
        include: ['carbon-components-svelte'],
        // carbon-icons-svelte is huge and takes 12s to prebundle, better use deep imports for the icons you need
        exclude: ['carbon-icons-svelte']
    }
});
Addeuz commented 1 year ago

Thanks for the quick response.

I tried to add carbon-components-svelte to exclude and that worked. But as you say the other option seems much more interesting. So I tried it.

And since we are using SvelteKit we can't but vite-plugin-svelte options there. We have to put them in our Kit config. So I tried that. And there was no change. I was expecting it to take long time to start from a cold start but it took the usual ~900 ms. And the issue as described in the first post is still there. Then I saw this https://github.com/sveltejs/kit/pull/7388, and from what I understand they by default now do { prebundleSvelteLibraries: true } until Vite 4.0 is out. But since I still experience these issues I figured that wasn't the problem for me...

I've tried to set the experimental option of useVitePreprocess to true as well. And that did no difference either.. So we might have to exclude optimization of carbon-components-svelte until we can figure this out...

This is our new vite.config.js:

import { sveltekit } from '@sveltejs/kit/vite';
import { resolve } from 'path';
import wasmPack from 'vite-plugin-wasm-pack';

/** @type {import('vite').UserConfig} */
const config = {
  define: {
    'process.env': process.env
  },
  resolve: {
    alias: {
      $components: resolve('./src/components'),
      $stores: resolve('./src/stores'),
      $types: resolve('./src/types')
    }
  },
  plugins: [sveltekit(), wasmPack('./sie-parser-wasm')],
  optimizeDeps: {
    // carbon-components-svelte is large, prebundle
    include: ['carbon-components-svelte'],
    // carbon-icons-svelte is huge and takes 12s to prebundle, better use deep imports for the icons you need
    exclude: ['carbon-icons-svelte']
  },
  ssr: {
    noExternal: ['@df/common']
  },

  server: {
    port: 3000
  }
};

export default config;

And our new svelte.config.js:

import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-static';
import { optimizeImports } from 'carbon-preprocess-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: [
    preprocess({
      scss: {
        includePaths: ['./src/styles/'],
        data: '@import "index.scss;"'
      }
    }),
    optimizeImports()
  ],
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: '404.html'
    })
  },
  vitePlugin: {
    prebundleSvelteLibraries: true,
    experimental: {
      useVitePreprocess: true,
      inspector: {
        toggleKeyCombo: 'meta-shift',
        showToggleButton: 'always',
        toggleButtonPos: 'bottom-right'
      }
    }
  }
};

export default config;
metonym commented 1 year ago

Thanks for digging into this and sharing your config. I hope prebundleSvelteLibraries can eventually replace the need for optimizeImports.

metonym commented 5 months ago

Commenting for posterity.

prebundleSvelteLibraries is now enabled by default in the Svelte Vite plugin.

This means that – for Vite/SvelteKit users – you do not necessarily need the optimizeImports preprocessor.

However, you will notice:

I would still recommend using optimizeImports and instructing Vite to exclude optimization of carbon-components-svelte, carbon-icons-svelte etc.. This is the best of both worlds; Carbon imports are already "pre-computed" and building for production will only traverse the used modules.

TLDR: using optimizeImports with Vite set-ups should still produce faster DEV cold starts as well as faster production build times.

Example vite.config.js:

import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import { optimizeCss, optimizeImports } from "carbon-preprocess-svelte";

/** @type {import('vite').UserConfig} */
export default {
  plugins: [
    svelte({
      preprocess: [vitePreprocess(), optimizeImports()],
    }),
    optimizeCss(),
  ],

  // Optional, but recommended for even faster cold starts.
  // Instruct Vite to exclude packages that `optimizeImports` will resolve.
  optimizeDeps: {
    exclude: [
      "carbon-components-svelte",
      "carbon-icons-svelte",
      "carbon-pictograms-svelte",
    ],
  },
};