callstack / linaria

Zero-runtime CSS in JS library
https://linaria.dev
MIT License
11.7k stars 416 forks source link

Linaria Vite #1299

Open lokeshwarobuli opened 1 year ago

lokeshwarobuli commented 1 year ago

Environment

Description

I was trying to install npm i vite-plugin-sentry. But when I build, it gives me an error stating

252824268-ababc910-c1a3-4720-812b-b19239739796

When I remove Linaria from my plugins in Vite.config.ts. Everything works as expected. Here is my config.ts

/// <reference types="vitest" />
import linaria from '@linaria/vite';
import { sentryVitePlugin } from '@sentry/vite-plugin';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    outDir: 'build',
    sourcemap: true,
  },
  plugins: [
    react(),
    linaria(),

    // Put the Sentry vite plugin after all other plugins
    sentryVitePlugin({
      org: 'bloomfilter',
      project: 'bloomfilter-web',
      // authToken: process.env.VITE_APP_SENTRY_AUTH_TOKEN,
    }),
  ],
  test: {
    globals: true,
    environment: 'jsdom',
    globalSetup: './src/test-globals.ts',
    setupFiles: './src/setupVitest.ts',
  },
  server: {
    port: 3000,
    host: '0.0.0.0',
    open: true,
  },
});

I opened an issue in https://github.com/getsentry/sentry-javascript-bundler-plugins and they suggested it might have something to do with Linaria may be. Any advice on how to proceed here. Thanks in advance

lokeshwarobuli commented 1 year ago

Any Updates on this one ??

Anber commented 1 year ago

Hi @lokeshwarobuli!

I use Linaria with Vite and Sentry, and it works well for me. Could you please provide more context? The repo with reproduced error would be amazing, but I understand that it may be complicated, so at least let's start from the content of components/brand/brand.tsx.

lokeshwarobuli commented 1 year ago

Hi @Anber. Linaria works perfectly with Vite even for me too. The problem starts when I try to add (https://github.com/getsentry/sentry-javascript-bundler-plugins) this package for a sentry issue following this URL https://docs.sentry.io/platforms/node/guides/connect/sourcemaps/uploading/vite/.

Then entire app blows up with messages as follows

Screenshot 2023-07-26 at 9 44 38 AM

and for your reference here is brand.tsx

import { styled } from '@linaria/react';
import { MouseEventHandler } from 'react';
import betaLogoLight from '../../assets/images/BF-Logo-Primary-RGB-Color_Black.svg';
import betaLogoDark from '../../assets/images/BF-Logo-Primary-RGB-Color_White.svg';

type BrandProps = {
  style: any;
  width: number;
  height: number;
  onClick: MouseEventHandler;
  darkMode?: boolean;
  clickable?: boolean;
};

export function Brand({
  style,
  width = 200,
  height = 90,
  onClick,
  darkMode = false,
  clickable = true,
}: Partial<BrandProps>) {
  return (
    <BrandContainer style={{ ...style, width, height }}>
      <img
        alt="Bloomfilter Logo"
        src={darkMode ? betaLogoDark : betaLogoLight}
        width="100%"
        height="100%"
        onClick={onClick}
        style={clickable ? { cursor: 'pointer' } : { cursor: 'default' }}
      />
    </BrandContainer>
  );
}

const BrandContainer = styled.div`
  margin-left: 10;
  display: flex;
  flex: 0.98;
  flex-direction: column;
  justify-content: center;
  align-items: center;
`;

Steps to reproduce:

  1. Run yarn add @sentry/vite-plugin --dev to a app that contains linaria, react and sentry.
  2. Update the vite.config.ts to the following below
    
    /// <reference types="vitest" />
    import linaria from '@linaria/vite';
    import { sentryVitePlugin } from '@sentry/vite-plugin';
    import react from '@vitejs/plugin-react';
    import { defineConfig } from 'vite';

// https://vitejs.dev/config/ export default defineConfig({ build: { outDir: 'build', sourcemap: true, }, plugins: [ react(), linaria(),

// Put the Sentry vite plugin after all other plugins
sentryVitePlugin({
  org: 'bloomfilter',
  project: 'bloomfilter-web',
  // authToken: process.env.VITE_APP_SENTRY_AUTH_TOKEN,
}),

], test: { globals: true, environment: 'jsdom', globalSetup: './src/test-globals.ts', setupFiles: './src/setupVitest.ts', }, server: { port: 3000, host: '0.0.0.0', open: true, }, });


3. Then run `tsc && vite build`. That is when the error in the above screenshot pops up
lokeshwarobuli commented 1 year ago

Any Updates on this. Were you guys able to re-produce or is there some more info needed from my side ?

Anber commented 1 year ago

Hi @lokeshwarobuli Yeah, we have a few similar bugs over there. I'll try to fix it asap.

lokeshwarobuli commented 1 year ago

@Anber Thanks eagerly waiting !!

Anber commented 1 year ago

Hi @lokeshwarobuli! I was a bit out of my mind yesterday :) It's not the same problem and needs future investigation, mainly because I don't have problems with the same setup. However, you can fix your config to make Vite run the Linaria plugin before sentryVitePlugin. You need to specify enforce: "pre" like this:

  plugins: [
    react(),
    {
        ...linaria(),
        enforce: 'pre',
    },

    // Put the Sentry vite plugin after all other plugins
    sentryVitePlugin({
      org: 'bloomfilter',
      project: 'bloomfilter-web',
      // authToken: process.env.VITE_APP_SENTRY_AUTH_TOKEN,
    }),
  ],
lokeshwarobuli commented 1 year ago

Hi @Anber. Thanks but that didn't work either. It is giving a different set of errors if I do the above mentioned way. Below is the screenshot of those errors

Screenshot 2023-07-30 at 4 54 56 PM
layershifter commented 1 year ago

@lokeshwarobuli I have managed to make it working, here is an example: https://stackblitz.com/edit/vitejs-vite-mvpj3w

The proper config is:

import { defineConfig } from 'vite';
import linaria from '@linaria/vite';
import react from '@vitejs/plugin-react';
import { sentryVitePlugin } from '@sentry/vite-plugin';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    {
      ...linaria({
        babelOptions: {
          presets: ['@babel/typescript'],
        },
      }),
      enforce: 'pre',
    },
    sentryVitePlugin({
      org: 'bloomfilter',
      project: 'bloomfilter-web',
      // authToken: process.env.VITE_APP_SENTRY_AUTH_TOKEN,
    }),
  ],
});

@Anber while it works now, we probably need to consider to use this.load() in Vite plugin.

lokeshwarobuli commented 1 year ago

@layershifter Thanks a lot. Let me check it out on my end

orzechowskid commented 11 months ago

we recently encountered this problem with vite@^4.5.0, @linaria/vite@^5.0.4, and @sentry/vite-plugin@^2.7.1. we worked around it by adding a path alias to babel-plugin-module-resolver in our linaria config file:

/* eslint-env commonjs */
module.exports = {
  babelOptions: {
    plugins: [
      [
        "module-resolver",
        {
          alias: {
            "~": "./src",
            "\0sentry-release-injection-file":
              "@sentry/bundler-plugin-core/sentry-release-injection-file",
          },
        },
      ],
    ],
    presets: [
      ["@babel/preset-react", {}],
      ["@babel/preset-typescript", {}],
    ],
  },
};

notice the leading \0 in the property name. we saw in our CI output that the injected module import had a bad character prepended to it:

image

I haven't had the time to track down whether this is a sentry bug or a linaria bug, but we were at least able to successfully build our app again.

in case it's important, the plugins section of our vite config file looks like this:

  plugins: [
    reactPreset(),
    tsconfigPaths(),
    linaria({
      exclude: ["**/node_modules/**", "src/global.css"],
    }),
    isSentryEnabled &&
      sentryVitePlugin({
        org: "<my-org>",
        project: "<my-app>",
        release: {
          name: process.env.VERSION,
        },
        authToken: process.env.SENTRY_AUTH_TOKEN,
      }),
  ],
Malien commented 7 months ago

This looks like a more overarching inability of linaria to work with "virtual modules", or transforms applied by the build pipeline in general (assuming your transformations are not done with the same babel config you pass to the linaria plugins).

For my use, I had funky-looking import specifiers that I've wrote special bundler plugins to resolve, load, and transform them. But since they don't really map to the "import a JS file" convention, linaria's sandbox fails to import it.

E.g.

import SvgComponent from "svg:./path/to/graphic.svg"
import resourceMap from "i18n:./path/to/translations/folder"
import partialStaticOptimizedHTML from "html:./unminified.partial.html"

To which plugins that resolve those preppend \0 to signify a "virtual module" as per convention.

This also answers @orzechowskid's question of:

I haven't had the time to track down whether this is a sentry bug or a linaria bug

It's intended as per (rollup?) convention to be a virtual module, loaded with a rollup/vite plugin (via the load hook).

The workflow is usually:

"funky-looking-import-specifier" ---[resolveId]--> "\0funky-looking-import-specifier" ---[load]--> "export default ..." --[transform]--> <final output>

Ideally linaria (by extension wyw-in-js) could've used this.load rollup API to get the final transformed code from the bundler directly, instead of just relying on the bundler to resolve ids to filenames, and then run babel to get runnable JS. This potentially could:

There might be a lot of difficulties in using bundler output instead of transforming the files ourselves in babel. I don't have the full picture. Last time I've checked I had difficulties even using this.load to get transformed source. Maybe @Anber might shed a light onto this issue.

For now I've wrote a simple babel plugin, inserted into the linaria transform pipeline, that changes

import SvgComponent from "svg:./path/to/graphic.svg"

to

const SvgComponent = () => null

It's a hacky af solution, but works fine for my use case.

Anber commented 7 months ago

Hi @Malien!

As far as I remember, we tried to use load, and it didn't work :(

orzechowskid commented 7 months ago

To which plugins that resolve those preppend \0 to signify a "virtual module" as per convention.

oh! thank you @Malien ! I wasn't aware of such a convention, having never used virtual modules before.