Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using rollup-plugin-import-assert Vite still imports CSS as a string rather than a CSSStyleSheet object #10633

Closed
7 tasks done
franktopel opened this issue Oct 25, 2022 · 8 comments
Labels
enhancement New feature or request p2-nice-to-have Not breaking anything but nice to have (priority)

Comments

@franktopel
Copy link

franktopel commented Oct 25, 2022

Describe the bug

I am importing a CSS module script using the new import assertions feature:

import sheet from './path/to/styles.css' assert { type: 'css' };

I am using rollup-plugin-import-assert to get a CSSStyleSheet object from that which later can directly be pushed into a web component's shadowRoot.adoptedStyleSheets.

Unfortunately, despite having configured this rollup plugin, Vite still imports sheet as a string.

To see what exactly I'm trying to do, see https://stackblitz.com/edit/vitejs-vite-evu9dn?file=FooBar.js.

Reproduction

https://stackblitz.com/edit/vitejs-vite-evu9dn?file=FooBar.js

Steps to reproduce

No response

System Info

System:
    OS: macOS 12.6.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 7.31 GB / 64.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    npm: 8.6.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
  Browsers:
    Brave Browser: 106.1.44.112
    Chrome: 106.0.5249.119
    Chrome Canary: 109.0.5380.0
    Firefox: 106.0.1
    Firefox Developer Edition: 103.0
    Safari: 16.1
    Safari Technology Preview: 16.4
  npmPackages:
    vite: ^3.1.0 => 3.1.8

Used Package Manager

npm

Logs

Vite log using `vite build --debug`, click to expand
  vite:config bundled config file loaded in 78.37ms +0ms
  vite:esbuild init tsconfck (root: /Users/connexo/Sites/XDC) +0ms
  vite:esbuild init tsconfck (root: /Users/connexo/Sites/XDC) +1ms
  vite:esbuild init tsconfck (root: /Users/connexo/Sites/XDC) +0ms
  vite:esbuild init tsconfck (root: /Users/connexo/Sites/XDC) +0ms
  vite:esbuild init tsconfck end +4ms
  vite:esbuild init tsconfck end +0ms
  vite:esbuild init tsconfck end +0ms
  vite:esbuild init tsconfck end +0ms
  vite:config using resolved config: {
  vite:config   build: {
  vite:config     target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
  vite:config     polyfillModulePreload: true,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: false,
  vite:config     cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
  vite:config     sourcemap: false,
  vite:config     rollupOptions: { plugins: [Array], acornInjectPlugins: [Array] },
  vite:config     minify: 'esbuild',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: { entry: 'src/components/components.ts', formats: [Array] },
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }
  vite:config   },
  vite:config   optimizeDeps: {
  vite:config     disabled: 'build',
  vite:config     force: undefined,
  vite:config     esbuildOptions: { preserveSymlinks: undefined }
  vite:config   },
  vite:config   configFile: '/Users/connexo/Sites/XDC/vite.config.ts',
  vite:config   configFileDependencies: [ '/Users/connexo/Sites/XDC/vite.config.ts' ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     optimizeDeps: { force: undefined },
  vite:config     build: {}
  vite:config   },
  vite:config   root: '/Users/connexo/Sites/XDC',
  vite:config   base: '/',
  vite:config   resolve: { alias: [ [Object], [Object] ] },
  vite:config   publicDir: '/Users/connexo/Sites/XDC/public',
  vite:config   cacheDir: '/Users/connexo/Sites/XDC/node_modules/.vite',
  vite:config   command: 'build',
  vite:config   mode: 'production',
  vite:config   ssr: {
  vite:config     format: 'esm',
  vite:config     target: 'node',
  vite:config     optimizeDeps: { disabled: true, esbuildOptions: [Object] }
  vite:config   },
  vite:config   isWorker: false,
  vite:config   mainConfig: null,
  vite:config   isProduction: true,
  vite:config   plugins: [
  vite:config     'vite:build-metadata',
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm-helper',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:wasm-fallback',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:build-html',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:force-systemjs-wrap-complete',
  vite:config     'vite:watch-package-data',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'rollup-plugin-import-assert',
  vite:config     'vite:dynamic-import-vars',
  vite:config     'vite:import-glob',
  vite:config     'vite:build-import-analysis',
  vite:config     'vite:esbuild-transpile',
  vite:config     'vite:terser',
  vite:config     'vite:reporter',
  vite:config     'vite:load-fallback'
  vite:config   ],
  vite:config   server: {
  vite:config     preTransformRequests: true,
  vite:config     middlewareMode: false,
  vite:config     fs: { strict: true, allow: [Array], deny: [Array] }
  vite:config   },
  vite:config   preview: {
  vite:config     port: undefined,
  vite:config     strictPort: undefined,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: undefined,
  vite:config     proxy: undefined,
  vite:config     cors: undefined,
  vite:config     headers: undefined
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(0) { set: [Function (anonymous)] },
  vite:config   createResolver: [Function: createResolver],
  vite:config   worker: {
  vite:config     format: 'iife',
  vite:config     plugins: [
  vite:config       'vite:build-metadata',
  vite:config       'vite:pre-alias',
  vite:config       'alias',
  vite:config       'vite:modulepreload-polyfill',
  vite:config       'vite:resolve',
  vite:config       'vite:html-inline-proxy',
  vite:config       'vite:css',
  vite:config       'vite:esbuild',
  vite:config       'vite:json',
  vite:config       'vite:wasm-helper',
  vite:config       'vite:worker',
  vite:config       'vite:asset',
  vite:config       'vite:wasm-fallback',
  vite:config       'vite:define',
  vite:config       'vite:css-post',
  vite:config       'vite:build-html',
  vite:config       'vite:worker-import-meta-url',
  vite:config       'vite:force-systemjs-wrap-complete',
  vite:config       'vite:watch-package-data',
  vite:config       'commonjs',
  vite:config       'vite:data-uri',
  vite:config       'vite:asset-import-meta-url',
  vite:config       'rollup-plugin-import-assert',
  vite:config       'vite:dynamic-import-vars',
  vite:config       'vite:import-glob',
  vite:config       'vite:build-import-analysis',
  vite:config       'vite:esbuild-transpile',
  vite:config       'vite:terser',
  vite:config       'vite:reporter',
  vite:config       'vite:load-fallback'
  vite:config     ],
  vite:config     rollupOptions: {},
  vite:config     getSortedPlugins: [Function: getSortedPlugins],
  vite:config     getSortedPluginHooks: [Function: getSortedPluginHooks]
  vite:config   },
  vite:config   appType: 'spa',
  vite:config   experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false },
  vite:config   getSortedPlugins: [Function: getSortedPlugins],
  vite:config   getSortedPluginHooks: [Function: getSortedPluginHooks]
  vite:config } +8ms
vite v3.1.8 building for production...
✓ 25 modules transformed.
dist/style.css   0.87 KiB / gzip: 0.40 KiB
dist/xdc.js      29.76 KiB / gzip: 9.12 KiB

Validations

@bluwy
Copy link
Member

bluwy commented Nov 9, 2022

This is likely caused by

if (!isDynamicImport && assertIndex > -1) {
str().remove(end + 1, expEnd)
}

where we strip import assertions by default as in most cases, we can handle the assets ourselves ootb.

I'm also not sure if CSS import assertions are to spec? Ideally Vite should align to import assertion behaviour by default so a separate plugin isn't needed, which is the case for JSON import assertions today.

@anil9973
Copy link

CSS import assertions is added in html spec. HTML Standard

Chrome and Edge support since v93. Firefox and Webkit were involved in the development of import assertions as a result of working out CSS modules, and are both currently implementing the prerequisites for CSS modules (constructible stylesheets and adopedStyleSheets).

Rollup v3.3.0 add support for import assertions.

Basic support for import assertions #4646

@bluwy
Copy link
Member

bluwy commented Nov 19, 2022

That's the spec for CSS module scripts, but I tested out CSS import assertions in Chrome and it does work, but it's not spec-approved yet. The proposal:

HTML and CSS modules are under consideration, and these may use similar explicit type syntax when imported.

We likely want to do this with first-class support but we'll have to see how it plays out first.

@bluwy bluwy added enhancement New feature or request p2-nice-to-have Not breaking anything but nice to have (priority) and removed pending triage rollup plugin compat feat: library mode labels Nov 19, 2022
@joezappie
Copy link

Just commenting to follow this thread. I'd love to be able to get rid of my workarounds to import CSSStyleSheets. Got excited when I saw #8937 was closed

@kasperpeulen
Copy link

@jrj2211 What workaround do you use?

@joezappie
Copy link

joezappie commented Jan 3, 2023

The workaround I use is using a different file extension for css files I want to import as a constructible style sheet and rollup-plugin-cssimport:

import cssStyleSheet from 'rollup-plugin-cssimport';
export default defineConfig(async () => ({
  plugins: [
    cssStyleSheet({ include: ['**/*.ccss'], options: { resolve: '/' } }),
  ],
}));

I then can import .ccss as as constructible style sheets:

import styles from './menu.ccss';
export class Menu extends LitElement {
  static styles = [styles];
}

I went with .ccss for "constructible cascading style sheets". Not a fan of this solution, but it was the only thing I could figure out on how to make it work without having to use JS in CSS. Cant wait for the day I can rename all my ccss files to .css and use assert instead!

@carlos-duran
Copy link

carlos-duran commented May 2, 2023

Edit: It looks like Import Assertions will be deprecated in favor of Import Attributes.

I'm not using any plugin but I can confirm that Vite 4.3 still has this issue.

import sheet from './styles.css' assert { type: 'css' }; // ❌ vite error

document.adoptedStyleSheets = [sheet];

I also tried this:

import sheet from './styles.css?inline' assert { type: 'css' };

document.adoptedStyleSheets = [sheet]; // ❌ error: sheet is not a CSSStyleSheet. It's a string.

@bluwy
Copy link
Member

bluwy commented May 4, 2023

Looks like I was mistaken, and CSS module scripts has been merge into the HTML spec. But given import assertions is being phased out, I'm not sure if it's worth pursuing that again. Similar: #12140

But re the rollup-plugin-import-assert plugin, the problem is that Vite appends ?used to the final CSS file, which the plugin fails to detect here. Removing the ?used is a separate task we like to remove in the future, but for now I think this can be fixed at the plugin-side, especially given the deprecation context.

I've made a Stackblitz to further analyze how the plugin transforms code.

@bluwy bluwy closed this as not planned Won't fix, can't repro, duplicate, stale May 4, 2023
@github-actions github-actions bot locked and limited conversation to collaborators May 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request p2-nice-to-have Not breaking anything but nice to have (priority)
Projects
None yet
Development

No branches or pull requests

6 participants