carbon-design-system / carbon-preprocess-svelte

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

Using optimizeImports() with SvelteKit causes error 500 `Unexpected token 'export'` #38

Closed willbicks closed 1 year ago

willbicks commented 2 years ago

Description

I'm trying out Carbon for the first time, and hoping to use it with SvelteKit. I had some success with adding some first components without a pre-processor, but the vite dev server was struggling to generate everything and pages were taking over a minute to load with components and icons. As such, I turned to the pre-processor, but ran into an issue where it caused page renders to fail. Below are the steps I followed reproduce this issue (used the sveltekit example as a template).

Steps to Reproduce

  1. npm create svelte@latest test-app
    • Skeleton Project
    • Yes, using TypeScript syntax
    • ESLint: yes
    • Prettier: yes
    • Playwright: no
  2. cd test-app
  3. npm install
  4. npm i -D carbon-components-svelte carbon-preprocess-svelte
  5. Edit ./src/routes/index.svelte

    • Add the following:

      <script>
          import "carbon-components-svelte/css/g100.css";
          import { Button, truncate } from "carbon-components-svelte";
      </script>
      
      <Button>Primary button</Button>
      
      <div use:truncate>Text...</div>
  6. Edit ./svelte.config.js

    • Adjust to match:

      import adapter from '@sveltejs/adapter-auto';
      import preprocess from 'svelte-preprocess';
      import { optimizeImports } from 'carbon-preprocess-svelte';
      
      /** @type {import('@sveltejs/kit').Config} */
      const config = {
          // Consult https://github.com/sveltejs/svelte-preprocess
          // for more information about preprocessors
          preprocess: [preprocess(), optimizeImports()],
      
          kit: {
              adapter: adapter()
          }
      };
      
      export default config;
  7. npm run dev

Actual Outcome

From there, the following error is found in the browser and the console:

500
Unexpected token 'export'
.\test-app\node_modules\carbon-components-svelte\src\Truncate\truncate.js:9
export function truncate(node, options = {}) {
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1032:15)
    at Module._compile (node:internal/modules/cjs/loader:1067:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:168:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:195:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24)

This issue goes away if optimizeImports() is removed, or if import { truncate } is removed. I haven't tested enough to know if it's also an issue for other function imports.

Relevant Versions

Node: v16.14.0

@sveltejs/kit: 1.0.0-next.377 svelte: 3.49.0

carbon-components-svelte: 0.67.1 carbon-preprocess-svelte: 0.9.1

Strunck commented 1 year ago

For me, I ran into the same issues. It took very long without the pre-processor. In @sveltejs/kit: 1.0.0-next.508 and with the adapter-node instead of adapter-auto in svelte.config.js so far all carbon-components-svelte seem to be working.

Here is my svelte.config.js

import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
import { optimizeImports  } from "carbon-preprocess-svelte";
/** @type {import('@sveltejs/kit').Config} */
const config = {    
    preprocess: [preprocess(),optimizeImports()],
    kit: { adapter: adapter(),  }
};
export default config;
stephane commented 1 year ago

Tested today with updated dependencies and the Cloudflare adapter. Now, it works! Build is a bit smaller 1.8M to 1.5M. Nice.

I was expecting a smaller build because my app is very simple but the CSS file still large (same size as before):

596K    _layout-981051fa.css

It tried to replace all import {Grid } from 'carbon-components-svelte' by import Grid from 'carbon-components-svelte/src/Grid/Grid.svelte'; as described in https://github.com/carbon-design-system/carbon-preprocess-svelte#optimizeimports but it produces the same build output.

metonym commented 1 year ago

@stephane optimizeImports rewrites component imports to speed up development and build compile times. There shouldn't be a difference in bundle output since unused imports should be tree-shaken when building for production.

optimizeCss might be what you're looking for if you want to decrease the final CSS size

willbicks commented 1 year ago

I'm happy to report that the config I originally posted seems to be working now, not sure if just some version changes fixed it or what exactly happened. Unfortunately, there still seem to be some issues with performance optimization. Using SvelteKit, and the svelte.config.js file posted above, loading a page with a datatable doesn't even start for ~1.5 minutes, and takes up to 6 minutes to finish:

image

Using vite in debug mode, I can see a whole bunch of icons and assets that aren't currently in use are being processed.

vite.config.js:

import { sveltekit } from '@sveltejs/kit/vite';
import { optimizeCss } from 'carbon-preprocess-svelte';

/** @type {import('vite').UserConfig} */
const config = {
    plugins: [sveltekit(), process.env.NODE_ENV === "production" && optimizeCss()],
    build: {
        target: [ 'es2020' ]
    }
};

export default config;

svelte.config.js:

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

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: [preprocess(), optimizeImports()],

    kit: {
        adapter: adapter()

    }
};

export default config;

Versions:

stephane commented 1 year ago

@metonym, I didn't mention I used optimizeCss and to be sure optimizeCss was enabled I removed the test against NODE_ENV.

My conf was:

import adapter from '@sveltejs/adapter-cloudflare';
import preprocess from 'svelte-preprocess';
import { optimizeImports, optimizeCss } from 'carbon-preprocess-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
        // Consult https://github.com/sveltejs/svelte-preprocess
        // for more information about preprocessors
        preprocess: [preprocess(), optimizeImports()],
        kit: {
                adapter: adapter()
        },
        vite: {
                plugins: [process.env.NODE_ENV === 'production' && optimizeCss()]
        }
};

export default config;
willbicks commented 1 year ago

Regarding the follow up concern I shared above regarding long load times, I'm happy to report that I was able to overcome that as well.

I was importing icons in a .ts file, which I'm guessing avoids pre-processing. By converting that TS file to a .svelte file with a <script context="module" lang="ts">, optimization is working again and my dev load times are reasonable.