esbuild-rails
esbuild-rails copied to clipboard
Support for bun package manager
Hello, firstly thanks for your plugin. Recently bun new package manager has been out, apparently faster than esbuild and its plugin interface is based on esbuild, but for some reason it does not works properly. For your information, there is a library called unplugin that allow to make a plugin works for multiple package manager : https://github.com/unjs/unplugin/issues/329
Other links: https://bun.sh/docs/runtime/plugins https://dev.to/jacobandrewsky/building-universal-jsts-plugins-with-unplugin-5328 https://bun.sh/docs/bundler/plugins https://bun.sh/docs/bundler/vs-esbuild
I can confirm it does not work at the moment, here is the code I used and the error I got :
import rails from 'esbuild-rails'
const result = await Bun.build({
entrypoints: [
'app/javascript/application.js'
],
naming: {
chunk: '[name]-[hash].digested'
},
splitting: true,
format: 'esm',
outdir: 'app/assets/builds',
plugins: [
rails()
]
})
error: undefined is not an object (evaluating 'args.pluginData.path')
/path/to/my/project/undefined/**/*_controller.ts:1:0 0
Might look into it if anyone has pointers
I try to customize it the plugin. In bun, there is no resolveDir and neither pluginData. My workflow of testing is:
CLI:
rails new bun-plugin-rails-app --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-active-record --skip-active-job --skip-active-storage --skip-action-cable --skip-jbuilder --skip-test --skip-system-test -j bun --main
cd bun-plugin-rails-app
Change in Gemfile:
gem "jsbundling-rails", github: "rails/jsbundling-rails"
CLI:
bundle update
rails javascript:install:bun
bundle update
mkdir -p app/javascript/public
echo 'console.log(new Date().toTimeString());' >> app/javascript/public/test.js
echo 'import "./**/*.js";' >> app/javascript/application.js
rails g controller pages home
bin/dev
open http://localhost:3000/pages/home
import path from 'path';
import fg from 'fast-glob';
// Transform filenames to controller names
// [ './admin/hello_world_controller.js', ... ]
// [ 'admin--hello-world', ... ]
function convertFilenameToControllerName(filename) {
return filename
.replace(/^\.\//, "") // Remove ./ prefix
.replace(/_controller.[j|t]s$/, "") // Strip _controller.js extension
.replace(/\//g, "--") // Replace folders with -- namespaces
.replace(/_/g, '-') //
}
// This plugin adds support for globs like "./**/*" to import an entire directory
// We can use this to import arbitrary files or Stimulus controllers and ActionCable channels
const railsPlugin = (options = { matcher: /.+\..+/ }) => {
const resolveMap = new Map();
return {
name: 'rails',
setup(build) {
build.onResolve({ filter: /\*/ }, async (args) => {
console.log("onResolve");
console.log(args);
resolveMap.set(args.importer + args.path, {
path: args.path,
resolveDir: path.dirname(args.importer),
})
return {
path: args.importer + args.path,
namespace: 'bun-rails',
};
});
build.onLoad({ filter: /.*/, namespace: 'bun-rails' }, async (args) => {
const resolveData = resolveMap.get(args.path);
console.log(`Searching for '${resolveData.path}' in ${resolveData.resolveDir}`);
let files = await fg(resolveData.path, { cwd: resolveData.resolveDir });
files = files.sort().filter(p => options.matcher.test(p));
files = files.map((filepath) => path.relative(resolveData.resolveDir, filepath));
console.log(files);
const controllerNames = files.map(convertFilenameToControllerName);
const importerCode = `
${files
.map((module, index) => `import * as module${index} from './${module}'`)
.join(';')}
const modules = [${controllerNames
.map((module, index) => `{name: '${module}', module: module${index}, filename: '${files[index]}'}`)
.join(',')}]
export default modules;
`;
return { contents: importerCode };
});
},
};
};
There is some logs remaining but if it can help you find a long term solution and better one.
Sorry about this. We will take a look on our end about adding these missing options to Bun.
Gonna close this as it's an issue with bun and not esbuild-rails.