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 = truepeople 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 |
|
How is this going? |
|
I am closing this PR since we need a different approach |
|
Maybe try using dynamic |
Closes #1771