egoist / esbuild-register

Transpile JSX, TypeScript and esnext features on the fly with esbuild
MIT License
984 stars 52 forks source link

how to handle css import? #42

Open sibelius opened 2 years ago

sibelius commented 2 years ago

I'm trying to run like this

node - esbuild-register ./script/some.ts

it breaks when hits a .css file

node_modules/emoji-mart/css/emoji-mart.css:1
.emoji-mart,
^

SyntaxError: Unexpected token '.'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Object.newLoader (app/node_modules/esbuild-register/dist/node.js:2262:9)

is there a way to make it "bundle" css

egoist commented 2 years ago

not sure about this use case, why would a node script import CSS 🤔

sibelius commented 2 years ago

we use node to process our frontend code to extract routes to be used on the backend

somecodingwitch commented 2 years ago

Can't bundle-css solve the issue? I didn't really understand the objective

nojvek commented 2 years ago

I encountered this today. This could be solved by changing the transformSync to register the default loaders like css/text/binary in addition to js.

sibelius commented 2 years ago

can you provide an example?

daniloab commented 2 years ago

@nojvek can you show me what you found?

Cerberus commented 2 years ago

Have you tried to create your own register like this ?

node -r ./esbuild-register.js ...
// ./esbuild-register.js
const { register } = require('esbuild-register/dist/node')

register({ extensions: ['.js', '.ts'] })

register({
  extensions: ['.css'],
  loader: 'file', // may be 'text' (depend on use-case)
})

However, this works for global style sheet (not CSS module).

sibelius commented 2 years ago

what about making handling css the default behavior? or consuming from some config file?

Cerberus commented 2 years ago

I'm not sure what does your default behavior mean..

If I understand correctly, you are trying to use emoji-mart that require this statement..

import 'emoji-mart/css/emoji-mart.css'

Set esbuild-register.js.

// ./esbuild-register.js
register({ extensions: ['.css'], loader: 'file' })

Just inject css file by adding useEffect like below.

import emojiCss from 'emoji-mart/css/emoji-mart.css'
// Simple utils
const injectLink = (url: string) => {
    const link = document.createElement('link')
    link.rel = 'stylesheet'
    link.type = 'text/css'
    link.href = url
    document.head.appendChild(link)

    return () => {
        document.head.removeChild(link)
    }
}
// In Component render function
useEffect(() => {
    return injectScript(emojiCss)
}, [])

When the component is rendered, the css file will be injected and rejected after unmount that.

PS: Only work for Client Side Rendering (CSR).

Cerberus commented 2 years ago

And don't forget to check this out https://esbuild.github.io/content-types/#css

esbuild-register support loader css too.

register({ extensions: ['.css'], loader: 'css' })