I'm building a big laravel application which will be split into multiple Laravel packages. Each package will supply it's own pages. So my pages are located somewhere in the project or in a vendor folder. They are not nicely together in one root folder. How can I make this work?
My current idea is to add a function to webpack.mix.js to search for pages in folders of the packages and to extend the Inertia::render function such that it will automatically point to the correct page for packages. What do you think?
Hi,
Personally, what I would do in this situation, is to leave Inertia's defaults as-is, but to use Laravel's built-in asset publishing mechanism for this. Here's how:
Assuming you're using Inertia's default resources/js/Pages path for your views, I'd start by adding the resources/js/Pages folder to your project's .gitignore file:
/node_modules
/public/hot
/public/storage
+/resources/js/Pages
/storage/*.key
...
Then, from there, in each of your packages, I would publish the Inertia views to your resources/js/Pages folder, so that they're all 'gathered' into one place by Laravel. You can do this in your Package's Service Provider:
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/path/to/views' => resource_path('js/Pages'),
], 'inertia');
}
Finally, we'll probably want to make sure that each time you run a composer command (install, update or dump), the correct views are published, as well as to 'override' them (using --force) if they already exist. This is also fairly easy, and can be done by adding one line to our application's composer.json file:
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi",
+ "@php artisan vendor:publish --tag=inertia --force"
],
Your views should now automatically be 'installed' into your application whenever you update or install your packages.
Do keep in mind that if you ever remove a file or package, you'll probably want to manually empty to resources/js/Pages folder, as it'll keep an 'old' version of the file. Alternatively, you can create an Artisan console command that does this for you.
Hope this helps!
That is a great idea, thanks!
How would you handle Pages which are packed in NPM packages?
@claudiodekker Great solution if you're using Composer!
However, if you're using NPM packages, I'd take a look at the resolveComponent callback. This callback allows you to map the page name (as provided by Inertia during the request) to whatever component you want.
For example, you could append pages supplied by your NPM packages with an identifier:
return Inertia::render('@PackageName::Event/Show');
And then within your resolveComponent callback you can parse this page name, and then modify the require. Maybe if there is @PackageName:: present, that could refer to an NPM package page components, but if it's omitted, you could just fallback to the app page components. Something like this:
new Vue({
render: h => h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent(name) {
if (name.startsWith('@PackageName::')) {
return // some NPM require
} else {
return require(`./Pages/${name}`).default
}
},
},
}),
}).$mount(app)
Does that help?
Answered within 20 minutes :100: Thanks, this helps a lot!
@iamniels You're quite welcome! 馃
@reinink How would you handle the layout? So I would like that the main application forces the use of a layout on pages of the packages.
@iamniels This, you could also do in the resolveComponent method. I personally do something like this in a few of my apps:
import MyPersistentLayout from "./Layouts/Persistent";
resolveComponent(name) {
const componentOptions = require(`./Pages/${name}`).default;
componentOptions.layout = (h, page) => h(MyPersistentLayout, [page]);
return componentOptions;
}
@claudiodekker Dig it, nice solution! 馃憤
Thanks! @claudiodekker
Most helpful comment
@claudiodekker Great solution if you're using Composer!
However, if you're using NPM packages, I'd take a look at the
resolveComponentcallback. This callback allows you to map the page name (as provided by Inertia during the request) to whatever component you want.For example, you could append pages supplied by your NPM packages with an identifier:
And then within your
resolveComponentcallback you can parse this page name, and then modify the require. Maybe if there is@PackageName::present, that could refer to an NPM package page components, but if it's omitted, you could just fallback to the app page components. Something like this:Does that help?