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
Add ESM plugins support #1773
Add ESM plugins support #1773
Conversation
If a plugin is defined like this: export default (opts) => {
return {
postcssPlugin: 'postcss-name',
Once(root) { /* ... */ }.
};
};
export const postcss = true; This doesn't quite work, because setting if (i.postcss === true) {
if (i.__esModule && i.default) {
i = i.default()
} else {
i = i()
}
} else if (i.postcss) {
i = i.postcss
} |
The origin idea of ESM plugins is: const plugin = () => {
…
}
plugin.postcss = true
export default plugin
|
I think given that the recommended CJS plugin declaration is module.exports = (opts = {}) => {
// Plugin creator to check options or prepare caches
return {
postcssPlugin: 'PLUGIN NAME'
// Plugin listeners
}
}
module.exports.postcss = true people will expect the ES6 version to be export default (opts = {}) => {
// Plugin creator to check options or prepare caches
return {
postcssPlugin: 'PLUGIN NAME'
// Plugin listeners
}
}
export const postcss = true |
hi when will it be merged |
@GrapevineLin when somebody will check that it works |
Sorry for letting this fall of my radar, @ai! Here are my test results: CJSNo optionsThis case works great! const postcss = require('postcss');
const plugin = require(...);
postcss([plugin]).process(...); OptionsPassing options to the plugin is pretty annoying. The object loaded by const postcss = require('postcss');
const plugin = require(...);
postcss([plugin.default(...)]).process(...); or const postcss = require('postcss');
const plugin = require(...).default;
postcss([plugin.default(...)]).process(...); both of which expose the implementation of the plugin as an ESM module to the user. Native ESMNo argumentsWorks great! import postcss from 'postcss';
import plugin from ...;
postcss([plugin]).process(...); ArgumentsSame problem as for CJS: you can't pass arguments directly to TypeScriptNo ArgumentsI get a type error from this code: import postcss from 'postcss';
import plugin from ...;
postcss([plugin]).process(...);
This could be pretty easily solved though by adding an explicit TypeScript example that suggests writing import type {Plugin, PluginCreator} from 'postcss';
export interface Options {
// ...
}
const plugin: PluginCreator<Options> = opts => {
return {
postcssPlugin: 'postcss-name',
Once (root) {
// Plugin code
}
}
}
plugin.postcss = true
export default plugin; ArgumentsThis one actually works (once I fix the type annotations)! import postcss from 'postcss';
import plugin from ...;
postcss([plugin(...)]).process(...);
|
I've poked around some more with conditional exports. Unfortunately, there doesn't seem to be a way to export a given file only for ESM-polyfill users. So unless PostCSS goes with Option 3 above, I think from a package author's perspective the best option is to accept that the old CommonJS syntax is the only thing that's universally usable and add a shim: module.exports = require('./build/index').default; along with @ai My recommendation to you is:
|
Update: It turns out TypeScript users can avoid a lot of this pain by using import type {PluginCreator} from 'postcss';
namespace plugin {
export interface Options {
// ...
}
}
const plugin: PluginCreator<plugin.Options> = opts => {
return {
postcssPlugin: 'postcss-name',
Once (root) {
// Plugin code
}
}
}
plugin.postcss = true;
export = plugin; This generates a CommonJS module just like the one you'd write in raw JS, without the need for the wrapper shims I described above. Unfortunately, it's not even vaguely ESM—that |
Unfortunately, Seems like a critical blocker for me. |
Check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feature/esm-plugins
How is this going? |
I am closing this PR since we need a different approach |
Maybe try using dynamic |
Closes #1771