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

Issues when using esbuild plugins #116

Closed
gBasil opened this issue Oct 31, 2021 · 6 comments
Closed

Issues when using esbuild plugins #116

gBasil opened this issue Oct 31, 2021 · 6 comments

Comments

@gBasil
Copy link

gBasil commented Oct 31, 2021

  • mdx-bundler version: ^6.0.2
  • node version: v16.2.0
  • npm version: 7.20.5

Relevant code or config

const { code, frontmatter } = await bundleMDX(postData, {
	cwd: path.join(process.cwd(), 'component'),
	esbuildOptions: options => {
		options.target = 'es2020';

		if (options.plugins) options.plugins = [
			sassPlugin(),
			...options.plugins
		];

		return options;
	}
});

What you did:

I tried two other plugins for using Sass with esbuild, but they all had a similar error.

What happened:

Console output:

wait  - compiling...
event - compiled successfully
 > index.jsx:1:28: error: Cannot import "../../../../../../AppData/Local/Temp/tmp-9916-zRcDS0um2TrJ/nextjs-blog/component/component.module.css" into a JavaScript file without an output path configured
    1 │ import componentStyles from './component.module.scss'
      ╵                             ~~~~~~~~~~~~~~~~~~~~~~~~~

error - Error: Build failed with 1 error:
index.jsx:1:28: error: Cannot import "../../../../../../AppData/Local/Temp/tmp-9916-zRcDS0um2TrJ/nextjs-blog/component/component.module.css" into a JavaScript file without an output path configured
    at failureErrorWithLog (C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:1493:15)
    at C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:1151:28
    at runOnEndCallbacks (C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:941:63)
    at buildResponseToResult (C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:1149:7)
    at C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:1258:14
    at C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:629:9
    at handleIncomingPacket (C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:726:9)
    at Socket.readFromStdout (C:\Users\gunne\Documents\Programming\node.js\sass-error\nextjs-blog\node_modules\esbuild\lib\main.js:596:7)
    at Socket.emit (node:events:365:28)
    at Socket.emit (node:domain:470:12) {
  errors: [
    {
      detail: undefined,
      location: [Object],
      notes: [],
      pluginName: '',
      text: 'Cannot import "../../../../../../AppData/Local/Temp/tmp-9916-zRcDS0um2TrJ/nextjs-blog/component/component.module.css" into a JavaScript file without an output path configured'
    }
  ],
  warnings: [],
  page: '/mdx'
}

Reproduction repository:

https://github.com/GunnerBasil/mdx-bundler-sass-plugins-issue

Problem description:

When using esbuild-plugin-sass with mdx-bundler, mdx-bundler or esbuild output an error about not being able to import the temporary file generated by esbuild-plugin-sass without configuring an output path.

Suggested solution:
If what I am doing is incorrect, it would be helpful to elaborate in the documentation on how to use plugins.

@Arcath
Copy link
Collaborator

Arcath commented Nov 4, 2021

By default mdx-bundler doesn't write the bundle to the disk, which is fine for js but once you start misxing in images and css it doesn't work.

It is easy enough to fix, if you take a look at my esbuildOptions I'm using an output directory so it can write images to a path.

You need to define options.outdir to the on-disk path of the output folder e.g. public/css/post/slug/ and options.publicPath to the url of the folder e.g. /css/post/slug/. Finally set options.write to true so it will write to the disk.

@gBasil
Copy link
Author

gBasil commented Nov 15, 2021

Hey, sorry for the super late response. I played around a few times to try and get it to work, and I think I'm very close, I just need the right loader for .scss files.

My esbuild configuration:

const { code } = await bundleMDX(source, {
	cwd: folder,
	esbuildOptions: options => {
		// For some reason, the default of `es5` gives errors. Oh well.
		 options.target = 'es2020';
		// Load the sass plugin (import { sassPlugin } from 'esbuild-sass-plugin')
		if (options.plugins) options.plugins = [
			...options.plugins,
			sassPlugin({
				basedir: '.'
			}),
		];
		// Add a loder for .scss files
		options.loader = {
			...options.loader,
			'.scss': '???' // I'm unsure as to what type to use here. 'css' throws errors and 'file' just copies over the .scss file
		}
		options.publicPath = '/mdx';
		// path.join(process.cwd(), 'public/mdx');
		options.outdir = outputFolder;
		options.write = true;

		return options;
	}
});

The React component throwing the error

import { useState } from 'react'
import pageStyles from '../styles/components/PostLink.module.scss'

/**
 * Link to a post
 */
const PostLink = (props: { slug: string }) => {
	const [post, setPost] = useState(); // To be used later

	return (<p className={pageStyles.cardSubtitle}>Some text</p>);
}

export default PostLink

I'm unsure on what to put for the .scss loader. Thank you for your help

@Arcath
Copy link
Collaborator

Arcath commented Nov 17, 2021

I'd suggest moving the SASS plugin to the top of the plugin list (before ...options.plugins). esbuild runs from top to bottom so its possible one of the other plugins is handling the sass and its not getting build correctly. None of the sass plugins I've looked at mention anything about having to set a loader.

@gBasil
Copy link
Author

gBasil commented Nov 18, 2021

The plugin properly compiles the .scss files into .css now, and outputs them into the proper directory, (public/mdx on the server, so /mdx is the public path in esbuildOptions,) but the outputted files aren't loaded by the Next.js application and the automatic classname generation also doesn't appear to work.

No requests to the compiled file:
image
No class is set:
image
The component and .scss file used in the above example:

import componentStyles from '../styles/components/MDX.module.scss'

const MDX = () => {
	return (<p className={componentStyles.red}>MDX Component</p>);
}

export default MDX
.red {
	color: red;
	background: yellow;
}

@gBasil
Copy link
Author

gBasil commented Nov 25, 2021

I managed to make it work with mdx-loader, by adding

webpack(config, options) {
  config.module.rules.push({
    test: /\.mdx?$/,
      use: [
        // The default `babel-loader` used by Next:
        options.defaultLoaders.babel,
        {
          loader: '@mdx-js/loader',
          /** @type {import('@mdx-js/loader').Options} */
          options: {/* jsxImportSource: …, otherOptions… */}
        }
    ]
  });
  
  return config
}

to next.config.js and using it with dynamic imports like so

// Your path will vary
const Component = dynamic(() => import(`../../../blog/${frontmatter.slug}/index.mdx`));

return (<NextPage>
    <Component /> {/* The important bit */}
</NextPage>)

@gBasil gBasil closed this as completed Nov 25, 2021
@benjammartin
Copy link

benjammartin commented May 10, 2022

If you encounter this issue. Pass it like this into getMDXComponent.

import YourComponent from 'components/YourComponent'
export default function Page({ code }: Props) {
  const Component = React.useMemo(() => getMDXComponent(code), [code])
  return <Component components={{...otherComponents, YourComponent}} />
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants