Giter Club home page Giter Club logo

esbuild-svelte's Introduction

esbuild-svelte

npm version npm downloads CI

Plugin to compile svelte components for bundling with esbuild.

Install

Install this plugin, esbuild and Svelte.

A simple build script looks like

import esbuild from "esbuild";
import sveltePlugin from "esbuild-svelte";

esbuild
  .build({
    entryPoints: ["app.js"],
    mainFields: ["svelte", "browser", "module", "main"],
    conditions: ["svelte", "browser"],
    bundle: true,
    outfile: "out.js",
    plugins: [sveltePlugin()],
    logLevel: "info",
  })
  .catch(() => process.exit(1));

The example-js folder of this repository is a great starting off point for a "complete" project. You can quickly get started using degit:

# Clone the JavaScript example to get started
npx degit EMH333/esbuild-svelte/example-js my-svelte-app

# Clone the TypeScript example to get started
npx degit EMH333/esbuild-svelte/example-ts my-svelte-app

CSS Output

By default, esbuild-svelte emits external css files from Svelte for esbuild to process. If this isn't desired, use a configuration that turns off external css output and instead includes it in the javascript output. For example: sveltePlugin({compilerOptions: {css: true}})

Typescript and Other Svelte Preprocessing

In order to support Typescript and other languages that require preprocessing before being fed into the Svelte compiler, simply add the preprocessor to the preprocess option (which accepts both a single preprocessor or an array of them). The example script below is a great place to start, you can also look at the example-ts folder for a more complete project.

import esbuild from "esbuild";
import esbuildSvelte from "esbuild-svelte";
import sveltePreprocess from "svelte-preprocess";

esbuild
  .build({
    entryPoints: ["index.js"],
    mainFields: ["svelte", "browser", "module", "main"],
    conditions: ["svelte", "browser"],
    bundle: true,
    outdir: "./dist",
    plugins: [
      esbuildSvelte({
        preprocess: sveltePreprocess(),
      }),
    ],
  })
  .catch(() => process.exit(1));

svelte exports condition

If you are importing a svelte component library, you need to add "svelte" to conditions in esbuild build options. This lets esbuild use the svelte property in svelte component's exports conditions in package.json .

Advanced

For incremental or watch build modes, esbuild-svelte will automatically cache files if they haven't changed. This allows esbuild to skip the Svelte compiler for those files altogether, saving time. Setting cache: false will disable this file level cache if an issue arises (please report).

You can see the full API for this plugin here, which includes support for Svelte's compiler options, preprocessing API, and more.

Developing

Clone, npm install, npm link and it's good to go! Releases are automated (with the right permissions), just by running npm version patch|minor|major.

esbuild-svelte's People

Contributors

alexxnb avatar bluegreenmagick avatar dependabot[bot] avatar emh333 avatar markoboy avatar prinzhorn avatar stoivo avatar tyler-boyd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

esbuild-svelte's Issues

compilerOptions css does not bundle external css files

If I set compilerOptions.css to true (or `inject with Svelte 4), it still generates a CSS file and doesn't include it in the Javascript file.

To Reproduce
Steps to reproduce the behavior:

Import a css file into a svelte file

Expected behavior
The CSS is included into the JS and get's injected

Environment:

  • esbuild-svelte version: 0.7.3
  • esbuild version: 0.18.10
  • svelte-preprocess: 5.0.4

Cache behavior is incorrect when using `preprocess`

Context: evanw/esbuild#1394. Here's an example:

const fs = require('fs');
const esbuild = require('esbuild');
const sveltePlugin = require('esbuild-svelte');
const { sass } = require('svelte-preprocess-sass');

(async () => {
  fs.writeFileSync(__dirname + '/app.js', 'import x from "./foo.svelte"\nconsole.log(x)');
  fs.writeFileSync(__dirname + '/foo.svelte', '<style lang="sass">@import "./xyz.sass"</style><div class="xyz">foo</div>');

  // Set color to red
  fs.writeFileSync(__dirname + '/xyz.sass', '.xyz\n  color: red');
  const result = await esbuild.build({
    entryPoints: ['app.js'],
    bundle: true,
    incremental: true,
    write: false,
    outfile: 'out.js',
    plugins: [sveltePlugin({
      preprocess: {
        style: sass(),
      },
    })],
    logLevel: 'info',
  });
  console.log(result.outputFiles[1].text);

  // Set color to green
  fs.writeFileSync(__dirname + '/xyz.sass', '.xyz\n  color: green');
  const result2 = await result.rebuild();
  console.log(result2.outputFiles[1].text);

  result.rebuild.dispose();
})();

This should print red followed by green. However, it prints red twice. I assume this is a result of #43. Explicitly adding cache: false is a workaround, and will generate red followed by green.

The problem here is that preprocessors can depend on additional files other than the input file such as when preprocessed CSS code uses @import. When that happens, those additional files must be included in the cache invalidation check. This is described in detail here: https://esbuild.github.io/plugins/#caching-your-plugin.

I can see two ways of fixing this bug:

  1. The easy way to fix this would be to just disable the cache if there is a preprocessor. Obviously that would result in it running more slowly, but it would at least still be correct.

  2. The hard way to fix this would be to use the dependencies returned by the preprocessor during cache invalidation. Specifically, the call to preprocess() here returns a dependencies property in addition to a code property. You would need to at least a) store those paths and the file contents along with the cached value and b) check the contents of those files when deciding later on whether or not the cache entry is valid. Make sure to handle the case where one of the files is missing (i.e. it was deleted), which should invalidate the cache entry.

I don't have a personal stake in fixing this bug. But I noticed that it was tripping people up, so I thought it would be good to report. Feel free to do whatever you want with this report.

Breaks watch mode on error when preprocess dependency transformation fails

Describe the bug
If preprocess fails execution of a dependency (eg: an external scss file imported within a <style> tag).
The onLoad returning watchFiles are lost and editing the external scss does not trigger the rebuild.

To Reproduce
Steps to reproduce the behavior:

  1. Create a .svelte file with a <style lang="scss"> with an external import @import "./external-file.scss"; with valid syntax.
  2. Start watch mode.
  3. Edit external-file.scss with some invalid syntax.
  4. Rebuild is triggered and fails.
  5. Edit external-file.scss with valid syntax.
  6. Rebuild is not triggered.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • esbuild-svelte version: 0.7.0
  • esbuild version: 0.14.42
  • Svelte preprocessors used (if any): SCSS

Option to enable svelte-check?

I just realized that esbuild-svelte doesn't do type checks, because svelte preprocessor doesn't do type checks.

I'd love to (optionally) include type checks in my esbuild run because they can save me a lot of runtime headaches.

It would be nice if this were an option in esbuild-svelte so I don't have to roll my own.

I suppose as a workaround I can hack it into my package.json scripts to just run before kicking off esbuild.

Typescript support

Does the plugin support typescript based svelte files? I tried running it, but getting errors with typescript syntax, and I'm unsure if I can configure the plugin to support it.

"esbuild-svelte" didn't set a resolve directory

When i use url() in css like:

content: url('img/img.jpg');
/* or */ 
background-image: url('img/img.jpg');

i have a error:

> fakecss:/path/to/Component.esbuild-svelte-fake-css:1:458: error: Could not resolve "img/img.jpg" (the plugin "esbuild-svelte" didn't set a resolve directory)

To Reproduce
REPO

Expected behavior
bundling url() to css πŸ€·πŸ»β€β™‚οΈ

  • esbuild-svelte version: latest
  • esbuild version: latest
  • Svelte preprocessors used (if any): sass

Can't build multi file project

I do get errors with imports and multiple svelte files. You have that in your example, what am I missing, do I need to have some special config?

 > src/App.svelte: error: Could not resolve "./Tailwindcss.svelte"
    14 β”‚ import Tailwindcss from "./Tailwindcss.svelte";

Example use with Typescript

Hi, Thanks for all your work on this project.

Describe the bug

I wanted to setup esbuild with svelt and typescript I tried to follow you guidelines as best as possible. I have some issue to import typescript files into a svelt component. I forked the project and added an example-ts. https://github.com/stoivo/esbuild-svelte

Esbuild seams to complain abount Joke and svelt-check seams unhappy too.

Svelt-check
β‹Š> ~/D/e/example-ts on main β¨― pnpm svelte-check

====================================
Loading svelte-check in workspace: /Users/simon/Downloads/esbuild-svelte/example-ts
Getting Svelte diagnostics...

/Users/simon/Downloads/esbuild-svelte/example-ts/index.svelte:5:3
Error: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. (ts)
  import {haha} from "$fun";
  import {Joke} from "$fun";
  import Second from "./second.svelte";


/Users/simon/Downloads/esbuild-svelte/example-ts/index.svelte:5:11
Error: 'Joke' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. (ts)
  import {haha} from "$fun";
  import {Joke} from "$fun";
  import Second from "./second.svelte";


/Users/simon/Downloads/esbuild-svelte/example-ts/index.svelte:7:7
Error: Variable 'inputBinding' implicitly has type 'any' in some locations where its type cannot be determined. (ts)
  import Second from "./second.svelte";
  let inputBinding;



/Users/simon/Downloads/esbuild-svelte/example-ts/index.svelte:18:5
Error: Variable 'inputBinding' implicitly has an 'any' type. (ts)
  function change() {
    inputBinding.value = "testing" + Math.round(Math.random() * 100);
  }


====================================
svelte-check found 4 errors, 0 warnings, and 0 hints



esbuild
β‹Š> ~/D/e/example-ts on main β¨― pnpm build

> @ build /Users/simon/Downloads/esbuild-svelte/example-ts
> node buildscript.js

 > index.svelte:25:9: error: No matching export in "fun.ts" for import "Joke"
    25 β”‚ import { Joke } from "$fun";
       β•΅          ~~~~

1 error
Errors:  Error: Build failed with 1 error:
index.svelte:25:9: error: No matching export in "fun.ts" for import "Joke"
    at failureErrorWithLog (/Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1475:15)
    at /Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1133:28
    at runOnEndCallbacks (/Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:923:63)
    at buildResponseToResult (/Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1131:7)
    at /Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1240:14
    at /Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:611:9
    at handleIncomingPacket (/Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:708:9)
    at Socket.readFromStdout (/Users/simon/Downloads/esbuild-svelte/example-ts/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:578:7)
    at Socket.emit (node:events:390:28)
    at addChunk (node:internal/streams/readable:315:12) {
  errors: [
    {
      detail: undefined,
      location: [Object],
      notes: [],
      pluginName: '',
      text: 'No matching export in "fun.ts" for import "Joke"'
    }
  ],
  warnings: []
} undefined

To Reproduce

  1. clone https://github.com/stoivo/esbuild-svelte
  2. cd example-ts
  3. pnpm install or npm install
  4. pnpm build
  5. pnpm typecheck

customElement option throws an error

Describe the bug
Today I upgraded esbuild-svelte to version 0.74 with Svelte 4 as dependency. In the migration guide it states, that the Tag-Option for custom components is deprecated with Svelte 4 and was replaced with the customElement option (see https://svelte.dev/docs/v4-migration-guide#custom-elements-with-svelte). Using this new option, the esbuild-svelte plugin throws following error:

<svelte:options> unknown attribute

To Reproduce
Steps to reproduce the behavior:

  1. Define a custom component tag with <svelte:options customElement="my-component">
  2. Include this component in an HTML file
  3. See error

Expected behavior
No error should be thrown. The error should only occur if the old option (tag) was used.

Environment:

  • esbuild-svelte version: 0.7.4
  • esbuild version: 0.17.5
  • Svelte preprocessors used (if any): svelte-preprocess - 5.0.3

Make Svelte a peer dependency

Is your feature request related to a problem? Please describe.

I didn't realize the Svelte version is tied to esbuild-svelte. I was looking through the release notes and noticed that Svelte upgrades were part of them. There's no reason that this package needs to push an update just for people to receive Svelte fixes. This means people are either locked into an outdated Svelte version or into a newer one that introduced a breaking bug.

Describe the solution you'd like

Make Svelte a peer dependency

Rollup has peer: https://github.com/sveltejs/rollup-plugin-svelte/blob/8bc5ee49fec60ce32ee2cf9f285461348bece75c/package.json#L32
Webpack has peer: https://github.com/sveltejs/svelte-loader/blob/5e7853f233d7be5592b0b5fc22da9b4d1a5b0c12/package.json#L32
Vite doesn't list it at all, only as dev: https://github.com/sveltejs/vite-plugin-svelte/blob/1f7834494621cdecffac27539a9246387f6eb710/package.json
Parcel doesn't list it at all but the install instructions contain the Svelte package: https://github.com/DeMoorJasper/parcel-plugin-svelte/blob/7733036ee1a5747da46a8155b35b24bf23914793/package.json

I'd put the minimum version to one that has the required API for esbuild-svelte to work.

Describe alternatives you've considered

I think if I have the latest Svelte in my dependencies then this also matches what esbuild-svelte needs, so it's technically not necessary to update esbuild-svelte to get the latest Svelte.

svelte@4 - compilerOptions.css as a boolean is deprecated

Describe the bug
compilerOptions.css as a boolean is deprecated. Use 'external' instead of false.

To Reproduce
Any compilations

Expected behavior
Use 'external' instead of false.

  • esbuild-svelte version: latest
  • esbuild version: latet
  • Svelte preprocessors used (if any): yes

Release plugin version 1.0.0

I am planning to release v1.0.0 of this plugin once Svelte 5 is released. esbuild development seems to have mostly stabilized so I'm feeling okay moving forward without esbuild reaching v1.

Some changes that will likely happen:

  • Minimum esbuild version set to v0.17.0 to simplify version support
  • Minimum Svelte version set to v4 (or v5 depending on how breaking the changes are) to simplify version support
  • Removal of overzealous cache option
  • #188
  • Stretch: #24
  • Stretch: Bump Svelte version to v4.2.1 to require sveltejs/svelte#9120

how combine with esbuild-coffeescript ?

I try to use coffeescript in svelte on my rails app and i don't understand how merge both :

#!/usr/bin/env node

const watch              = process.argv.includes("--watch");
const esbuild            = require('esbuild')
const coffeeScriptPlugin = require('esbuild-coffeescript');
const esbuildSvelte      = require('esbuild-svelte');
const sveltePreprocess   = require('svelte-preprocess');

esbuild
  .build({
    entryPoints: ["app/javascript/svelte_src.js"],
    bundle: true,
    outfile: "app/assets/builds/svelte.js",
    plugins: [
      esbuildSvelte({
        preprocess: sveltePreprocess(/*{coffeescript: { bare: true }}*/),
      }),
      coffeeScriptPlugin({bare: true}),
    ],
    logLevel: "debug",
    watch: watch
  })
  .catch(() => process.exit(1));

I tried add plugin at the different place, but not working...

I find https://github.com/svelte-add/coffeescript but with rails we use esbuild and there is not sveltekit, so I cant use this... how can I do?

Unexpected token error with latest svelte-preprocess v5

Describe the bug
esbuild-svelte started throwing errors after upgrading svelte-preprocess and TypeScript (I upgraded both for peer deps conflict)

$ node build.js 
✘ [ERROR] Unexpected token [plugin esbuild-svelte]

    MyComponent.svelte:2:13:
      2 β”‚ 1: <script type="typescript">
        β•΅              ^

2:   import type { Foo } from './foo';
                 ^
3: 
4:   const foo: Foo = 'bar';

  The plugin "esbuild-svelte" was triggered by this import

    index.ts:1:24:
      1 β”‚ import MyComponent from './MyComponent.svelte';
        β•΅                         ~~~~~~~~~~~~~~~~~~~~~~

To Reproduce

Run the build script where the followings are installed

package.json

{
  "private": true,
  "dependencies": {
    "esbuild": "^0.17.16",
    "esbuild-svelte": "^0.7.3",
    "svelte": "^3.58.0",
    "svelte-preprocess": "^5.0.3",
    "typescript": "^5.0.4"
  }
}

(I confirmed the lock file tells the save versions.)

build.js

const esbuild = require('esbuild');
const esbuildSvelte = require('esbuild-svelte');
const path = require('path');
const sveltePreprocess = require('svelte-preprocess');

esbuild
  .build({
    entryPoints: [path.resolve(__dirname, './index.ts')],
    mainFields: ['svelte', 'browser', 'module', 'main'],
    bundle: true,
    outdir: path.resolve(__dirname, './dist'),
    plugins: [
      esbuildSvelte({
        preprocess: sveltePreprocess(),
      }),
    ],
  })
  .catch(() => process.exit(1));

MyComponent.svelte

<script type="typescript">
  import type { Foo } from './foo';
…

Expected behavior

Compile them as well as recent versions

Screenshots

N/A

Environment (please complete the following information):

  • esbuild-svelte version: 0.7.3
  • esbuild version: 0.17.16
  • Svelte preprocessors used (if any): 5.0.3

Additional context

  • It works with previous versions: svelte-preprocess v4.10.7 and TypeScript v4.9.5
  • Importing values works. Only type seems problematic
  • Tried on Node.js v16.19.1, v18.15.0

FEATURE: caching unmodified files

It would be nice to see a caching feature in this plugin. I use this plugin with esbuild + filewatcher and modified your plugin with a few lines for my needs.

...
const fileCache = {}
...
            //main loader
            build.onLoad({ filter: /\.svelte$/ }, async (args) => {

                const cached = fileCache[args.path]
                if (cached && fs.statSync(args.path).mtime < cached.time) {
                    return cached.data
                }

...

                    fileCache[args.path] = {
                        time: new Date(),
                        data: { contents, warnings: warnings.map(convertMessage) }
                    }

                    console.log(args.path + " compiled")
                    return fileCache[args.path].data
                } catch (e) {
                    return { errors: [convertMessage(e)] }
                }
...

This modification was made to version 0.3.1. I hope to see such a caching feature in your plugin in a future version, so that I do not have to use my modified version.

Thank you

dev-mode does not seem to be enabled

Describe the bug
I enabled dev within compilerOptions, but it does not seem like it does get enabled.

To Reproduce
Steps to reproduce the behavior:

  1. Set up a build with esbuild, and use this plugin, enabling dev under compilerOpptuions:
  const result = await build({
  plugins: [
    pnpPlugin(),
    sveltePlugin({
      compilerOptions: {
        dev: true,
      },
      preprocess: sveltePreprocess(),
    }),
  ],
  1. Attempt to use Svelte Devtools in Chromium

Expected behavior
Expected the browser-plugin to be able to connect.

Screenshots
I get this message:

To connect to Svelte perform a hard refresh (ctrl+F5) or click here.

Not working? Did you...
Use Svelte version 3.12.0 or above?
Build with dev mode enabled?

image

Environment (please complete the following information):

  • esbuild-svelte version:
  • esbuild version:
  • Svelte preprocessors used (if any):

Additional context
I checked if the problem was related to sveltejs/svelte-devtools#69 but the problem also exists with version 96 and 97 of Chromium.

versions:
Chromium: 96.0.4664.110 Arch Linux

"svelte": "^3.46.4",
"svelte-inview": "^2.1.1",
"@tsconfig/svelte": "^3.0.0",
"esbuild-svelte": "^0.6.3",
"eslint-plugin-svelte3": "^3.4.1",
"prettier-plugin-svelte": "^2.6.0",
"svelte-preprocess": "^4.10.4",
"svelte-preprocess-sass": "^2.0.1",

Problems getting Svelte components' internal CSS styles

Is your feature request related to a problem? Please describe.
I am having problem getting the internal styles to work. My build script (adapted from a different package) looks as follows:

const esbuild = require("esbuild");
const sveltePlugin = require("esbuild-svelte");

const args = process.argv.slice(2);
const watch = args.includes('--watch');
const deploy = args.includes('--deploy');

let opts = {
	entryPoints: ['js/app.js'],
	bundle: true,
	target: 'es2016',
	outdir: '../priv/static/assets',
	logLevel: 'info',
	plugins: [
		sveltePlugin({compilerOptions: {css: true}})
	]
};

if (watch) opts = { ...opts, watch, sourcemap: 'inline' };
if (deploy) opts = { ...opts, minify: true };

const promise = esbuild.build(opts);

if (watch)
{
	promise.then(_result => {
		process.stdin.on('close', () => {
			process.exit(0)
		});

		process.stdin.resume();
	})
}

And the "watcher" part of configuration:

	watchers: [
		# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
		#esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
		tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]},
		node: ["buildscript.js", "--watch", cd: Path.expand("../assets", __DIR__)]
	]

Describe the solution you'd like
I'd like to be able to combine the Svelte specific CSS with the remaining CSS coming from other sources into app.css

Describe alternatives you've considered
I read https://github.com/EMH333/esbuild-svelte#css-output and considered adding said options but that didn't work for me either

Additional context
I am trying to make things work again after migrating an Elixir/Phoenix project from Phoenix 1.5 with "webpack" to 1.6 with "esbuild". It's been a bumpy road but everything now seem to work except the said CSS not being available anywhere. My understanding is that this is caused by regular "tailwind" watcher overwriting esbuild-svelte's app.css inside priv/static/assets/ directory. I understand that it might not be an esbuild-svelte issue per se but would still be very grateful for some pointers / ideas how to tackle the problem.

Svelte on m1 bug with precompiled svelte/internal sources.

Svelte on m1 bug with precompiled svelte/internal sources.
When component unmount from slot i have this error:

image

When un/mount component in slot in localy imported module with this file structure:

  • distImportedModule
  • srcImportedModule
    • app
      • distApp
      • srcApp

image

TESTED SOURCES ONLY FOR M1 arm64 architecture

Source code for example.
If you download it - remove rollup bundler.

Or zip example.

External Svelte module errors when using a Svelte import

Describe the bug
If you use onMount (or most likely any Svelte import) with Svelte being external (by doing something like external: ['./node_modules/*'] in your build config) you get the following error:

[email protected]/node_modules/svelte/internal/index.mjs:1050 Uncaught (in promise) Error: Function called outside component initialization
    at get_current_component ([email protected]/node_modules/svelte/internal/index.mjs:1050)
    at onMount ([email protected]/node_modules/svelte/internal/index.mjs:1073)
    ...

To Reproduce
Steps to reproduce the behavior:

  1. Add external: ['./node_modules/*'] to your esbuild config
  2. Use onMount (or most likely any other Svelte import) in a .svelte file

Expected behavior
The error doesn't appear

Environment (please complete the following information):

  • esbuild-svelte version: 0.7.3
  • esbuild version: 0.17.11
  • Svelte preprocessors used (if any): [email protected]

Additional notes
I am compiling to ESM

Updating examples to use the 0.17.x esbuild "context API"?

Is your feature request related to a problem? Please describe.
Updating esbuild to any of the 0.17 versions breaks "watch mode". This is described in the esbuild documentation that the option was simply removed for ... reasons

Describe the solution you'd like
I would like to be able to properly use "watch" mode again after updating esbuild to 0.17.x or later. It probably doesn't require any changes to esbuild-svelte (I guess ?) but rather to example buildscript.js files

ENOENT error with latest version

Hello , I was using esbuild-svelte for my Svelte Application(svelte+typescript+tailwindcss) and so far all good. But,when I updated svelte-preprocess to latest version , it will not build .

image

Steps to reproduce:

@EMH333 , Please resolve this issue as soon as possible . Thank you for esbuild-svelte.

Can't resolve fakecss-path with splitting: true

One more time ))) I just want explain situation:

I have splitting bundles with css-chunks, but i can't load css on page...

Screenshot 2021-03-21 at 10 01 24

index.js
Screenshot 2021-03-21 at 10 09 45

index.css
Screenshot 2021-03-21 at 10 09 19

I have some resolver for this, but its not working with splitting: true...

let fakecsspathResolvePlugin = {
    name: 'fakecsspath',
    setup(build) {
        let path = require('path')

        build.onResolve({ filter: /\.esbuild-svelte-fake-css$/ }, ({ path }) => {
            return { path, namespace: 'fakecss' }
        })

        build.onLoad({ filter: /\.esbuild-svelte-fake-css$/, namespace: 'fakecss' }, ({ path }) => {
            const css = cssCode.get(path);
            return css ? { contents: css, loader: "css" } : null;
        })
    },
}

Can’t run example as is

When I try to load in the generated files in the example using a basic HTML wrapper like the one below, I’m getting an empty HTML page (the script and styles load but nothing is rendered):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test</title>
  <link rel="stylesheet" href="./entry.css">
</head>
<body>
  <script type="module" src="./entry.js"></script>
</body>
</html>

If I replace binding: document.body with target: document.body in entry.js, the app shows up. So, the following entry.js works insofar as the app displaying in the browser:

import Test from './index.svelte';

new Test({
  target: document.body,
});

However, if you click the button, you get the following error:

Uncaught TypeError: lol is undefined
  change https://localhost/entry.js:448
  listen https://localhost/entry.js:56
  m https://localhost/entry.js:411
  mount_component https://localhost/entry.js:194
  init https://localhost/entry.js:268
  Index https://localhost/entry.js:455
  <anonymous> https://localhost/entry.js:462

esbuild-svelte breaks watch mode on error

Describe the bug
When esbuild-svelte encounters and error it seems to break the watch mode of esbuild.

After the error occurs, esbuild doesn't rebuild the file after it has been saved again.

This is my EsBuild config:

esbuild.build({
  entryPoints: ['index.js'],
  bundle: true,
  outdir: 'dist',
  plugins: [
    sveltePlugin({
      compilerOptions: {
        css: false,
        hydratable: true
      }
    })
  ],
  minify: false,
  incremental: true,
  watch: {
    onRebuild (error, result) {
      if (error) console.error('SVELTE watch build failed:', error);
    }
  },
  logLevel
}).catch((error) => {
  console.log(error);
});

To Reproduce
Steps to reproduce the behavior:

  1. Create a Svelte file with an error
<script>
	import Something
</script>

<div>Hello</div>
  1. The plugin will produce this error:
✘ [ERROR] [plugin esbuild-svelte] Unexpected token
  1. After correcting the file and saving, watch mode will not rebuild.

Expected behavior

After the plugin reports and error, and the error is corrected, EsBuild should rebuild again but it doesn't.

Environment (please complete the following information):

  • esbuild-svelte version: ^0.6.3
  • esbuild version: ^0.14.23

cssOutputFilename not working

Describe the bug
Setting the cssOutputfilename in the compiler options has no effect.

To Reproduce
Add the css filename option in the example:

import { build } from "esbuild";
import sveltePlugin from "esbuild-svelte";

build({
  entryPoints: ["./entry.js"],
  mainFields: ["svelte", "browser", "module", "main"],
  bundle: true,
  outfile: "./dist/bundle.js",
  plugins: [
    sveltePlugin({
      compilerOptions: { cssOutputFilename: "foo.css" },
    }),
  ],
}).catch((err) => {
  console.error(err);
  process.exit(1);
});

Expected behavior
The dist folder should contain bundle.js and foo.css, but it contains bundle.js and bundle.css

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • esbuild-svelte version: 0.7.0
  • esbuild version: 0.14.32

Unexpected token

Describe the bug
A clear and concise description of what the bug is.

 > src/MetaData.svelte:2:17: error: [plugin: esbuild-svelte] Unexpected token
    2 β”‚ 1: <script lang="ts">
      β•΅                  ^
2:   export let title: string, description: string, image: string, url: string;
                     ^
3: </script>
4:

   src/index.ts:1:26: note: The plugin "esbuild-svelte" was triggered by this import
    1 β”‚ export * as MetaData from './MetaData.svelte'
      β•΅                           ~~~~~~~~~~~~~~~~~~~

To Reproduce

The file that causes the error:

<script lang="ts">
	export let title: string, description: string, image: string, url: string;
</script>

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • esbuild-svelte version: 0.6.3
  • esbuild version: 0.12.24
  • Svelte preprocessors used (if any):

Additional context
Add any other context about the problem here.

PostCSS/Tailwind JIT not recompiling correctly in watch mode

Describe the bug

We use tailwindcss/postcss as part of our svelte-preprocess config (sveltePreprocess({ postcss: true })), and with esbuild-svelte, if we add new tailwind classes (ie. not appearing in our existing code), watch triggers an incremental build but tailwindcss doesn't seem to be re-running...or if it is, it's not noticing the new classes.

The issue is fixed by restarting the esbuild-svelte process (the first build always runs tailwind correctly), so it's not very severe as there is an easy workaround.

To Reproduce
Steps to reproduce the behavior:

  1. Start using a new tailwindcss class in a .svelte file (eg. invisible)
  2. Hit save
  3. Wait for incremental build to finish and refresh the browser

Expected behavior
New tailwind class works (eg. the element disappears due to the invisible class)

Environment (please complete the following information):

Additional context

Maybe there's something simple I'm missing? I know this might not be an esbuild-svelte issue, but I'm sure others will eventually run into the same problem. I'm happy to post more of the config if that'll help, or even a small repro. I just wanted to hear your thoughts first before spending time on that (in case there's something obvious).

Thanks again for your work on this project!

line numbers inaccurate

Describe the bug
We have a fairly large production Svelte app and was trying to migrate off rollup to esbuild. Thanks for your plugin. We are running into an issue I was hoping you can give some hints too. We are running esbuild with watch and I am creating fake errors to test the error output so we can hook up an overlay screen. The issue I am running into, is the line numbers for svelte errors are off or strange.

  1. error in js
{"errors":[{"location":{"column":17,"file":"src/components/AppRoot.svelte","length":15,"line":79,"lineText":"import Left from \"./Left.svelte\";","namespace":"","suggestion":""},"notes":[],"pluginName":"esbuild-svelte","text":"Transform failed with 1 error:\nsrc/components/Left.svelte:321:7: error: Expected identifier but found \".\""}],"warnings":[]}

AppRoot.svelte imports Left.svelte and the error i introduced does exist at Left.svelte:321:7 but it is in the "text" area, not the "location"

  1. error in markup. An error I introduce in markup section at line 404, shows this output. The error line reported is 323, which isn't close to actual error location
{"errors":[{"location":{"column":10,"file":"src/components/Left.svelte","length":0,"line":323,"lineText":"321:           {room.name}\n322:         </a>\n323:         {##if roomID === room.id}\n               ^\n324:           <div\n325:             class=\"nav-action\"","namespace":"file","suggestion":""},"notes":[{"location":{"column":17,"file":"src/components/AppRoot.svelte","length":15,"line":79,"lineText":"import Left from \"./Left.svelte\";","namespace":"","suggestion":""},"text":"The plugin \"esbuild-svelte\" was triggered by this import"}],"pluginName":"esbuild-svelte","text":"Expected if, each or await"}],"warnings":[]}
  1. An error in css. Actual error is at line 625, output incorrectly shows 544
{"errors":[{"location":{"column":3,"file":"src/components/Left.svelte","length":0,"line":544,"lineText":"542: \n543: <style>\n544:   ..account-alert {\n        ^\n545:     background-color: var(--rml-warning-bg);\n546:     padding: var(--rml-padding-default);","namespace":"file","suggestion":""},"notes":[{"location":{"column":17,"file":"src/components/AppRoot.svelte","length":15,"line":79,"lineText":"import Left from \"./Left.svelte\";","namespace":"","suggestion":""},"text":"The plugin \"esbuild-svelte\" was triggered by this import"}],"pluginName":"esbuild-svelte","text":"Identifier is expected"}],"warnings":[]}

To Reproduce
Unfortunately I can't recreate this issue with a blank Svelte app.

Here is my build script though in case it helps.

const result = await esbuild
  .build({
    define: {
      __env_vars__: cfg,
    },
    entryPoints: ['src/app.js', 'src/room.ts'],
    bundle: true,
    outdir: outDir,
    assetNames: 'assets/[name]-[hash]',
    logLevel: 'debug',
    minify: false,
    sourcemap: true,
    // splitting: true,
    watch: {
      onRebuild(error) {
        clients.forEach((res) =>
          res.write(
            'data: ' +
              JSON.stringify({ update: true, error: error, path: appPath }) +
              '\n\n',
          ),
        );
        clients.length = 0;
        console.log(error ? JSON.stringify(error) : '...success...');
      },
    },
    format: 'esm',
    target: 'es2017',
    loader: {
      '.svg': 'text',
    },
    // metafile: true,
    plugins: [
      esbuildSvelte({
        preprocess: [
          typescript({
            sourcemap: true,
          }),
          sveltePreprocess({
            sourceMap: true,
            typescript: false,
          }),
        ],
      }),
    ],
  })
  .catch(() => process.exit(1));

Expected behavior
Location data would always be present in esbuild output on failure and point to correct line in file.

Environment (please complete the following information):

"esbuild": "^0.13.12",
"esbuild-svelte": "^0.5.7",
  • Svelte preprocessors used (if any):
    "svelte-preprocess": "^4.9.8",
    "svelte-preprocess-esbuild": "^2.0.0"

Thanks in advance!

Proper CSS Code splitting

Is your feature request related to a problem? Please describe.
This plugin code splits everything really well, but it is a bit weird at code splitting CSS. It generates a separate .css file for the code-splitted component, but inlines its styles right into the main index.css too. The other file is never loaded, and index.css does all the work.

I'm not sure whether this is a missing feature or a bug, but it seems like the generated code splitted .js file doesn't load its .css file, so maybe it's a missing feature.

Describe the solution you'd like
CSS should be code splitted well, and the splitted .css files be loaded when the respective splitted .js is loaded

Describe alternatives you've considered
Going with the flow here for now

And hey, love this plugin, it's saved so much time and amazing to integrate with ESBuild. Keep up the great work!

Invalid source map if using prepreprocessors

Hello,

I use esbuild with this plugin and I have found the following problem if I enable source map generation with css set to false in compileOptions

const esbuild_svelte = require("esbuild-svelte/configurable")({
    compileOptions: { css: false, hydratable: true },
    preprocessor: svelteConfig.preprocess,
}

I think the source of the problem is in your code at configurable/index.js line 44:

                    //if svelte emits css seperately, then store it in a map and import it from the js
                    if (!compileOptions.css && css.code) {
                        let cssPath = args.path.replace(".svelte", ".esbuild-svelte-fake-css").replace(/\\/g, "/");
                        cssCode.set(cssPath, css.code + `/*# sourceMappingURL=${css.map.toUrl()}*/`);
                        contents = `import "${cssPath}";\n` + contents;
                    }

If I remove the \n the source map line is ok:

...
                        contents = `import "${cssPath}";` + contents;
...

I don't know if this will fix the problem completely. Possibly there is another way in esbuild to inject the css without modifying the contents.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.