Coder Social home page Coder Social logo

Comments (18)

sebastiandedeyne avatar sebastiandedeyne commented on July 19, 2024 9

Contrary to Blade, Inertia doesn't look for views, they're just strings.

You have full control over your own app.js, which is where the views can be resolved as you see fit.

Quick example:

return Inertia::render('my-package::Home/Index');
new Vue({
  render: h => h(InertiaApp, {
    props: {
      initialPage: JSON.parse(app.dataset.page),
      resolveComponent: name => {
        if (name.startsWith('my-package::')) {
          return require(`../../vendor/my/package/resources/js/Pages/${name.substr(12)}`).default
        }
        
        return require(`./Pages/${name}`).default
      }
    },
  }),
}).$mount(app)

Inertia doesn't impose any conventions regarding your frontend code, so I'm not sure what can be done to streamline this.

from inertia-laravel.

beeglebug avatar beeglebug commented on July 19, 2024 3

I've also hit this. I have some of my optional routes defined inside a package, and the javascript component ends up being published out to resources/vendor/MyPackage/js/Pages/MyPackagePage.js

In the package controller, I can't just do return Inertia::render('MyPackagePage'); because that would look inside resources/js/Pages, I would need to do something like:

return Inertia::render('../vendor/MyPackage/js/Pages/MyPackagePage');`

which isn't ideal, and doesn't even seem to work.

from inertia-laravel.

yashiroiori avatar yashiroiori commented on July 19, 2024 2

This is may solution to call and component from modules and packages

app.js
The structure to call is:
Params to from Module:
Type[Module]/PathToResourcesAssetsJsPages/ViewName.vue
Params to from Package:
Type[Package]/PathToVendorFolder/VendorName/PackageName/PathToResourcesAssetsJsPages/ViewName.vue
image

Call from modules using https://github.com/nWidart/laravel-modules
image

Module file structure modulo it's default use the package when create a new module
image

Call from package
image

Packges file structure are usually
image

webpack.mix.js
image

from inertia-laravel.

vortechron avatar vortechron commented on July 19, 2024 2

my current implementation for laravel package

resources/js/app.js

new Vue({
    render: (h) =>
        h(InertiaApp, {
            props: {
                initialPage: JSON.parse(app.dataset.page),
                resolveComponent: (name) => {
                    let splited = name.split('::')

                    if (splited.length == 1) return require(`./Pages/${name}`).default
                    
                    let [first, page] = splited
                    let [author, plugin] = first.split('/')

                    // '~': path.resolve('vendor')
                    return require(`~/${author}/${plugin}/resources/js/Pages/${page}`).default
                },
            },
        }),
}).$mount(app);

Author/PackageName/Controller/DashboardController.php

class DashboardController extends Controller
{
    public function index()
    {
        return inertia('author/package-name::Dashboard');
    }
}

i hope there is a better and proper way to implement inertiajs return view on laravel package.

from inertia-laravel.

ycs77 avatar ycs77 commented on July 19, 2024 2

OK. I think I got the answer. Thanks all for the ideas, inspired me to create a plugin.


Inertia Plugin

Warning: This plugin status is experimental, don't use it for the production application.

The plugin page loader for Inertia.js, powered by unplugin, supports Vite and Laravel Mix.

Define the namespace mapping for plugins pages directory, also can be extract namespace from the npm / composer package:

// webpack.mix.js
const InertiaPlugin = require('inertia-plugin/webpack')

mix
  .webpackConfig({
    plugins: [
      InertiaPlugin({
        namespaces: ({ npm, composer }) => [
          // define namespace mapping:
          { 'my-package-1': 'node_modules/my-plugin1/src/Pages' },

          // load namespace from npm package:
          npm('my-plugin2'),

          // load namespace from composer package:
          composer('ycs77/my-php-package'),
        ],
      }),
    ],
  })

The npm package like node_modules/my-plugin2/package.json:

{
  "name": "my-plugin2",
  "inertia": {
    "my-npm-package": "src/other-pages"
  }
}

The composer package like vendor/ycs77/my-php-package/composer.json:

{
    "name": "ycs77/my-php-package",
    "extra": {
        "inertia": {
            "my-php-package": "resources/js/Pages"
        }
    }
}

Will can be used namespace prefix get the view:

Inertia::render('my-package-1::Page3');
Inertia::render('my-npm-package::Page222');
Inertia::render('my-php-package::PhpPackagePage');

For full usage see the docs.

Try it~ 😊

from inertia-laravel.

herpaderpaldent avatar herpaderpaldent commented on July 19, 2024

I would love this feature too, however i found my way around this which i gonna post here in hope it might help you?

for production i publish the resources to the app's resource folder:

/*
         * to publish assets one can run:
         * php artisan vendor:publish --tag=web --force
         * or use Laravel Mix to copy the folder to public repo of core.
         */
        $this->publishes([
            __DIR__ . '/public/img' => public_path('img'),
            __DIR__ . '/resources/js' => resource_path('js'),
            __DIR__ . '/resources/sass' => resource_path('sass'),
            $this->getPackageJsonFile() => base_path('package.json'),
            $this->getPackageLockJsonFile() => base_path('package-lock.json'),
        ], 'web');

during development i have npm run watch running and refering the pages in my package alike (note the copyDirectoryWatched)

if (! mix.inProduction()) {
  mix.js('resources/js/app.js', 'public/js')
      .sass('resources/sass/app.scss', 'public/css')
      .copyDirectoryWatched('packages/seatplus/web/src/resources/js/Pages/Configuration', 'resources/js/Pages/Configuration')
      .webpackConfig({
        output : {chunkFilename: 'js/[name].js?id=[chunkhash]'},
        resolve: {
          alias: {
            vue$: 'vue/dist/vue.runtime.esm.js',
            '@' : path.resolve('resources/js'),
          },
        },
      })
  
}

Like this you are able to work out your package as you would do it in the main application.

from inertia-laravel.

beeglebug avatar beeglebug commented on July 19, 2024

The only problem with that is that the app.js would need to be aware of all the possible packages in order to resolve the paths, rather than the package being able inject themselves.

The suggestion from OP seems better in terms of isolation / injection, you would tell inertia that you have views in a package folder, and then when you call Inertia::render('my-package::Component'), it could internally check the map of namespaces and convert the component argument before passing it down to the javascript.

This would allow the javascript resolveComponent function to remain unaware of the existence of any packages.

from inertia-laravel.

beeglebug avatar beeglebug commented on July 19, 2024

I've spent a bit longer on this today and realised @sebastiandedeyne is right. You need the requires to have at least the partial path to allow webpack to statically analyse the lazy load possibilities, so doing it inside the componentResolver makes a lot more sense.

from inertia-laravel.

robsontenorio avatar robsontenorio commented on July 19, 2024

Just wondering at this point a guide about creating packages with Inertia would be a nice addition :)

from inertia-laravel.

robsontenorio avatar robsontenorio commented on July 19, 2024

For future reference here is my approach. Built a package as a standalone dashboard using inertia, where target app does not has inertia or laravel mix.

https://github.com/robsontenorio/lighthouse-dashboard

from inertia-laravel.

herpaderpaldent avatar herpaderpaldent commented on July 19, 2024

@vortechron this looks very promising i am likely ditching my approach in favors of yours

from inertia-laravel.

herpaderpaldent avatar herpaderpaldent commented on July 19, 2024

i gave @vortechron 's solution a try and i wasn't satisfied. running dev/prod with npm took way to long.

from inertia-laravel.

maicol07 avatar maicol07 commented on July 19, 2024

I'm also interested on this feature. Has anyone found a workaround for this?

from inertia-laravel.

yashiroiori avatar yashiroiori commented on July 19, 2024

I'm also interested on this feature. Has anyone found a workaround for this?

Actually work with modules package + inertiajs + vue/react + bootstrap/tailwind

from inertia-laravel.

maicol07 avatar maicol07 commented on July 19, 2024

@yashiroiori can you explain how did you manage to setup the packages, so that views are loaded with Inertia?

from inertia-laravel.

devappsoftware avatar devappsoftware commented on July 19, 2024

@yashiroiori can you explain how did you manage to setup the packages, so that views are loaded with Inertia?

+1

from inertia-laravel.

jenky avatar jenky commented on July 19, 2024

I think this can be done using symlink and I had it working on my local but there are few things need to be addressed.

This is an example directory

.
├── app
├── resources/
│   └── js/
│       ├── app.js
│       └── Pages/
└── vendor/
    └── my-package/
        ├── config/
        ├── src/
        │   └── ServiceProvider.php
        └── js/
            ├── ComponentA.vue
            └── ComponentB.vue

In your package ServiceProvider, register the component hint path

Inertia::loadComponentsFrom(__DIR__.'/../js', 'my-package');

Then have artisan command similar to storage:link to generate the symlink from vendor/my-package/js to resources/js/Pages/vendor

.
├── app
├── resources/
│   └── js/
│       ├── app.js
│       └── Pages/
│           └── vendor/
│               └── my-package -> symlink to vendor/my-package/js/
└── vendor/
    └── my-package/
        ├── config/
        ├── src/
        │   └── ServiceProvider.php
        └── js/
            ├── ComponentA.vue
            └── ComponentB.vue

In your controller you can use something like this

Inertia::render('my-package::ComponentA');

It will replace the the component from my-package::ComponentA to vendor/my-package/ComponentA and you don't have to update your app.js

The command can be added to composer post-autoload-dump script to generate the symlink automatically. However there is a case when assets are published to resources folder, the symlink need to be updated also. The good news is there is VendorTagPublished event for this but the bad news is it only available since Laravel 8. I can create a PR for this when I have time to address this issue.

How do you guys think about this approach?

from inertia-laravel.

anditsung avatar anditsung commented on July 19, 2024

my current implementation for laravel package

resources/js/app.js

new Vue({
    render: (h) =>
        h(InertiaApp, {
            props: {
                initialPage: JSON.parse(app.dataset.page),
                resolveComponent: (name) => {
                    let splited = name.split('::')

                    if (splited.length == 1) return require(`./Pages/${name}`).default
                    
                    let [first, page] = splited
                    let [author, plugin] = first.split('/')

                    // '~': path.resolve('vendor')
                    return require(`~/${author}/${plugin}/resources/js/Pages/${page}`).default
                },
            },
        }),
}).$mount(app);

Author/PackageName/Controller/DashboardController.php

class DashboardController extends Controller
{
    public function index()
    {
        return inertia('author/package-name::Dashboard');
    }
}

i hope there is a better and proper way to implement inertiajs return view on laravel package.

when i try to use this. i have an error javascript heap out of memory
looks like it will compile all the package.

from inertia-laravel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.