DEV Community

Shane Rosenthal
Shane Rosenthal

Posted on

Dynamic Imports On Laravel Vapor With Vue Router

Recently I have been playing around with Laravel Vapor which is fresh approach to the common Laravel "monolithic" server we have grown to trust, love and hate at times. And while Vapor delivers on it's promises to "Launch your Laravel infrastructure on Vapor and fall in love with the scalable simplicity of serverless." it does have some caveats that are handled differently than what you are used to.

A few months ago Jason Beggs wrote up a wonderful post about Using Dynamic Imports with Laravel Mix which in essence, splits up your Vue components js files into separate files, instead of storing and loading everything in the common app.js file. This approach will certainly speed up your load times and give your users a better experience. Let's see how it works:

Adding support for dynamic imports

First, we are going to add a babel.rc file into the root of our project and add support for dynamic imports like so:

{
  "plugins": [
    "@babel/plugin-syntax-dynamic-import"
  ]
}

Alternatively, as Jason points out, we can add the config directly to our webpack.mix.js file:

mix.babelConfig({
  plugins: ['@babel/plugin-syntax-dynamic-import'],
});

For Vue Router I have a router.js file with all of my routes, instead of importing all of my components for each route we use a different function to load the right component on the right page (route). The 'webpackChunkName' tells webpack the name of the file that it should create for us.

{
    path: '/dashboard/videos',
    name: 'videos',
    component: () => import(/* webpackChunkName: "videos" */ './components/Videos/Videos'),
},
{
    path: '/dashboard/images',
    name: 'images',
    component: () => import(/* webpackChunkName: "images" */ './components/Images/Images'),
},

Locally, with npm run watch and checking out the JS console networking tab, we can see our different JS files being loaded on each relevant page.

Make sure, if you have import statements at the top of your route file to comment/delete them or web pack will load the component from app.js.

Now for the fun part, deploying to Vapor

Since Vapor does not store your public files inside of a public directory on your server, because there is no server we cannot access these files in our environment the same way we do locally. The Vapor Docs tell us that Vapor creates an environment variable that points to our asset directory which is inside of an AWS S3 bucket that Vapor creates for us. Additionally Vapor injects that variable into our front end code, allowing us to reference those files with

process.env.ASSET_URL

Now all we need to do is tell webpack where those dynamically imported files are coming from. In your webpack.mix.js file add:

if (mix.inProduction()) {
    const ASSET_URL = process.env.ASSET_URL + "/";

    mix.webpackConfig(webpack => {
        return {
            plugins: [
                new webpack.DefinePlugin({
                    "process.env.ASSET_PATH": JSON.stringify(ASSET_URL)
                })
            ],
            output: {
                publicPath: ASSET_URL
            }
        };
    });
}

And see our dynamic files importing as we would expect, directly from our Vapor S3 bucket!

A couple "gotchas".

We are now needing to npm run prod on our staging environment for our webpackConfig to be registered. In your vapor.yml file change the staging build section to

build:
   - 'composer install'
   - 'php artisan event:cache'
   - 'npm install && npm run prod && rm -rf node_modules'

In your layout file where you are pulling in the app.js/app.css files we need to make sure we are pulling from mix locally, and assets in our Vapor environments.

@if (app()->environment('local'))
   <script src="{{ mix('js/app.js') }}" defer></script>
   <link href="{{ mix('css/main.css') }}" rel="stylesheet">
@else
   <script src="{{ asset('js/app.js') }}" defer></script>
   <link href="{{ asset('css/main.css') }}" rel="stylesheet">
@endif

Now we can

vapor deploy staging --message="Adds dynamic import support"

And see our js files chunked into smaller bits, streamlining the users experience in Vapor!

Happy deploying!

Top comments (2)

Collapse
 
kevnk profile image
Kevin Kirchner

This saved me from a LOT of hassle. Thank you!

Collapse
 
galbanes profile image
galbanes

Thank you!!!