Loading chunks from dynamic imports though CDN URL like other assets
Asked Answered
H

2

7

I have a CDN pointing to my base domain, there is 1:1 mapping basically. I'm trying to build my bundle on the server, and I want to load it using CDN URL. What I want to have after npm run build is:

public/
  css/
    app.css
  js/
    index.js
    1.js.gz
    1.js
    2.js.gz
    2.js

And then my CDN will reflect that, so I want these resources to be loaded like this:

https://mycdn.com/public/js/index.js
https://mycdn.com/public/css/app.css

My current webpack.mix.js config:

mix
  .sass('resources/sass/app.css', 'public/css')
  .js('resources/js/index.js', 'public/js')

It generates all files in the proper location, which is good. Then I include them in my index.blade.php:

<script src="{{ elixirCDN('/js/index.js') }}"></script>

elixirCDN is my custom function:

function elixirCDN($file)
{
    $cdn = '';

    if(config('system.cdn_url'))
    {
        $cdn = config('system.cdn_url');
    }

    return $cdn . elixir($file);
}

It basically prepends filename with CDN url, so it all works fine.

The problem begins when I use dynamic imports, like this:

const Home = () => import("./Home")

The ideal situation would be that it also loads with the CDN:

https://mycdn.com/public/js/1.js

but instead, it doesn't, it loads with a relative path and my base domain:

https://mybasedomain.com/public/js/1.js

Obviously, because it's dynamic. How can I make my chunks to be loaded from the CDN as well?

I've tried to set publicPath as my CDN url, but it doesn't have any effect. I've also tried setPublicPath() but it's the same.

Heliogabalus answered 28/4, 2020 at 11:7 Comment(0)
D
1

Hi this is not the definitive answer but a step in the right direction. I got into this issue because my conditional import broke after updating all the webpack and babel packages.

Before the dynamic import you need to set the temporary public path for webpack to the location of the chunck which webpack needs to import dynamically

__webpack_public_path__ = 'https://cdn.dev.acsi.eu/eurocampings/assets/dev/dist/';

Than the import works

import(/* webpackChunkName: "state" */ './modules/BookingState/State')
        .then(({createState}) => {
            createState();
            this.renderEurocampingsWebsite(window);
        });

For me the dynamic import works, however it seems that the conditional import before, all the package updates, was working in without async behavior...

Just found out that Webpack has more magical comments, which can make the code behave procedural, at the cost of having both modules imported for the conditional import. This might also be helpful

import(
            /* webpackChunkName: "state" */
            /* webpackMode: "eager" */
            /* webpackPreload: true */
            './modules/BookingState/State'
        )
        .then...
Diaghilev answered 18/8, 2020 at 8:45 Comment(0)
I
0

I had a similar problem, where my main script was loaded into another page, and when loading chunks it tried loading them from the root url instead of the cdn.

Using the answer above, I came to the following solution:

in root imported file

export function setWebpackToLoadChunksFromScriptUrl() {
  const scriptPath: string = (document.currentScript as any || {}).src;
  const loadPath = scriptPath ? scriptPath.substring(0, scriptPath.lastIndexOf('/')) : '';
  if (loadPath) {
    __webpack_public_path__ = loadPath;
  }
}
setWebpackToLoadChunksFromScriptUrl();

export async function loadApplication(elementId: string) {
  const { loadApplicationOnHtmlElement } = (await import('./loaded-app'));
  loadApplicationOnHtmlElement((elementId));
}

Immediately answered 18/7, 2022 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.