Multiple javascript_pack_tag calls for different packs in one template hierarchy #1348
-
Hey there, I am facing an issue with the way different packs can be used in one template hierarchy. It looks like it's not okay to include two different packs within the same template (or make another call in a lower level of the template hierarchy). Let's say I have this directory tree inside app/javascript, assuming packs is the default, so: app/javascript/packs
lets say, I define two packs: // foo.js
const ReactRailsUJS = require("react_ujs");
const context = require.context("fooDir", true);
ReactRailsUJS.useContext(context);
// bar.js
const ReactRailsUJS = require("react_ujs");
const context = require.context("barDir", true);
ReactRailsUJS.useContext(context); Now In a template file (in my case .slim), I assumed, that shipping two packs like this, was possible: = javascript_pack_tag 'fooDir'
= javascript_pack_tag 'barDir'
/ and I can now call all sorts of components, like:
= react_component('barDir/FooComponent')
= react_component('fooDir/BarComponent')
But this wont work, because for two reasons: A) rails is complaining:
And B) the Namespace is wrong:
And this is essentially where my problem is, the way the namespaces are constructed, is not making it possible for me to use more than one pack, which in turn would enable me to be very granular in bundle splits. That's at least my understanding... I did refer to the docs (I probably read these several times at this point), and from what I understood, I can just make one call with two packs as args (at least that's what I saw in a place in my codebase): = javascript_pack_tag 'fooDir', 'barDir'
= react_component('FooComponent')
= react_component('BarComponent')
But this will not work, because the last pack in the call will set the namespace (barDir) so FooComponent cannot be found. Which will also lead to an error... In short, I need a way to make these kinds of splits, but I cannot afford to remove packs, like for example only to use fooDir. I have to work with the fact, that upwards in the template hierarchy is lots of legacy code both from sprockets and react code, that just won't go away any time soon. I know that in theory, I could just move all of the code into either fooDir or barDir, and call it a day. But a much much more preferred choice would be to have two namespaces, so this is possible: = javascript_pack_tag 'fooDir', 'barDir'
/ creates fooDir and barDir namespace
/ using namespaces to point to components
= react_component('fooDir/FooComponent')
= react_component('barDir/BarComponent')
Or at least some hackery way of achieving this... Is this possible? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Moving the files into a single directory is definitely the easiest solution. |
Beta Was this translation helpful? Give feedback.
-
For those of you who are suffering the same problem, I have a solution (more or less): You can't declare different namespaces. But you can use a re-export trick to at least keep your file structure like I described. Say you have two directories: foo and bar. What you could do is re-export your given components under a common pack-namespace, let's call it root. You can, of course, name it however you like. Now you only defined the pack for the common pack, like this for example: // packs/root.js
const ReactRailsUJS = require("react_ujs");
const context = require.context("root", true);
ReactRailsUJS.useContext(context); You can now call components from the root pack with its namespace, say we got this Tree:
= javascript_pack_tag 'root'
/ creates root namespace
/ using namespaces to point to components
= react_component('HelloRoot.tsx') Now, when you want to use Foo.tsx and Bar.tsx as create a file that re-exports the original reference. I like to have a dedicated folder to keep the namespaces correct, but you can do it however you like. So this would yield something like this:
// example for Foo.tsx, but same goes for any file
// root/_forwarding_/foo/FooForwarded.ts
// note that you can also define .tsx / jsx. files if you for some reason want to augment something on the component
// in my case I treat these dir just as re-exporting directory, not source code directories
// thats why I only need .ts / .js files for the re-export
// depending on your config, you might need to use relative imports
import Foo from "./foo/Foo";
// important: It must be the DEFAULT export!
export default Foo; Note that it does not matter which name the original component file had; the reference will now live under the name of the exported File. = javascript_pack_tag 'root'
/ using namespaces to point to components
= react_component('HelloRoot.tsx')
/ this will work now!
= react_component('_forwarding_/foo/FooForwarded') Maybe that will help some people! Best Sam |
Beta Was this translation helpful? Give feedback.
For those of you who are suffering the same problem, I have a solution (more or less):
You can't declare different namespaces. But you can use a re-export trick to at least keep your file structure like I described.
Say you have two directories: foo and bar. What you could do is re-export your given components under a common pack-namespace, let's call it root. You can, of course, name it however you like.
Now you only defined the pack for the common pack, like this for example:
You can now call components from the root pack with its namespace, sa…