Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken async chunk URLs from resetting public path #11

Open
daun opened this issue May 4, 2021 · 3 comments
Open

Broken async chunk URLs from resetting public path #11

daun opened this issue May 4, 2021 · 3 comments

Comments

@daun
Copy link

daun commented May 4, 2021

Describe the bug
Starting in v0.1.3, this plugin resets the publicPath config key to solve an issue with duplicate slashes. However, this will break loading async chunks in projects that define a custom publicPath and which don't load their assets from the root / but some subfolder like /dist/assets/.

Expected behavior
The plugin shouldn't modify any previously set publicPath.

Suggested fix
I've previously fixed the double-slash issue by adding a manifest transform. Maybe adding this as a default transform makes resetting the public path unnecessary. OTOH, you'd need to be smart about merging the default transform with any user-supplied transform array.

const fixDoubleSlashes = (manifestEntries) => {
  const manifest = manifestEntries.map(entry => {
    entry.url = entry.url.replace('//', '/')
    return entry
  })
  return { manifest, warnings: [] }
}

mix.generateSW({
  manifestTransforms: [fixDoubleSlashes]
})
@MathiasWeisheit
Copy link

MathiasWeisheit commented Jun 9, 2021

I have the same problem. I searched two days for the problem!
My Entry Script tries to load the assest from the wrong url: E.g. /dashboard/1.js instead of /1.js
I also fixed the double slash issue, but with modifyURLPrefix in the workboxConfig
modifyURLPrefix: { '//': '/', },
It works fine with Version 0.1.2

https://webpack.js.org/configuration/output/#outputpublicpath
output.publicPath defaults to 'auto' with web and web-worker targets, see this guide for its use cases.

Why do you set the publicPath to '' ?

Here is my complete mix file:

const { EnvironmentPlugin } = require('webpack')
const mix = require('laravel-mix')
const glob = require('glob')
const path = require('path')
const lang = require('laravel-vue-lang/mix') //https://www.npmjs.com/package/laravel-vue-lang
require('laravel-mix-workbox');

/*
 |--------------------------------------------------------------------------
 | Mix config
 |--------------------------------------------------------------------------
 */

mix.options({
    postCss: [require('autoprefixer')],
    hmrOptions: {
        host: '127.0.0.1',
        port: 8081 //https://laravel-mix.com/docs/5.0/hot-module-replacement
    }
});

/*
 |--------------------------------------------------------------------------
 | Babel config
 |--------------------------------------------------------------------------
 */
mix.babelConfig({
    plugins: ['@babel/plugin-syntax-dynamic-import'] //https://hephaistos.atlassian.net/browse/AP-434
})
/*
 |--------------------------------------------------------------------------
 | Webpack config
 |--------------------------------------------------------------------------
 */
mix.webpackConfig({
    plugins: [
        new EnvironmentPlugin({
            //Application's public url
            BASE_URL: '/'
        })
    ],
    module: {
        rules: [{
            test: /node_modules(?:\/|\\).+\.js$/,
            loader: 'babel-loader',
            include: [
                path.join(__dirname, 'node_modules/bootstrap-vue'),
                path.join(__dirname, 'node_modules/vuejs-datepicker'),
                path.join(__dirname, 'node_modules/vue-echarts'),
                path.join(__dirname, 'node_modules/resize-detector'),
                path.join(__dirname, 'node_modules/vue-c3'),
                path.join(__dirname, 'node_modules/vue-masonry'),
                path.join(__dirname, 'node_modules/vue-cropper'),
                path.join(__dirname, 'node_modules/vuedraggable'),
                path.join(__dirname, 'node_modules/vue-simplemde'),
                path.join(__dirname, 'node_modules/sweet-modal-vue'),
            ],
            options: {
                presets: [['@babel/preset-env', { targets: 'last 2 versions, ie >= 10' }]],
                plugins: [
                    '@babel/plugin-transform-destructuring',
                    '@babel/plugin-proposal-object-rest-spread',
                    '@babel/plugin-transform-template-literals'
                ],
                babelrc: false
            }
        }, {
            test: /resources[\\\/]lang.+\.(php|json)$/,
            loader: 'laravel-localization-loader',
        },
        { //eslint
            enforce: 'pre',
            exclude: /(node_modules)|(resources\/assets\/src\/vendor)/,
            loader: 'eslint-loader',
            test: /\.(js|vue|json)?$/,
            options: {
                fix: true,
                cache: false
            }
        }
        ]
    },
    resolve: {
        alias: {
            '@': path.join(__dirname, 'resources/assets/src'),
            '~': path.join(__dirname, './resources/assets/src'),
            '@lang': path.resolve('./resources/lang'), //https://www.npmjs.com/package/laravel-vue-lang
            'node_modules': path.join(__dirname, 'node_modules')
        }
    },
    output: {
        //chunkFilename: 'js/chunks/[name].js',  // https://hephaistos.atlassian.net/browse/AP-591
        //path: mix.config.hmr ? '/' : path.resolve(__dirname, './public/build')
    }
})

/*
 |--------------------------------------------------------------------------
 | Vendor assets
 |--------------------------------------------------------------------------
 */

function mixAssetsDir(query, cb) {
    (glob.sync('resources/assets/' + query) || []).forEach(f => {
        f = f.replace(/[\\\/]+/g, '/');
        cb(f, f.replace('resources/assets', 'public'));
    });
}

const sassOptions = {
    implementation: () => require('node-sass')
};

// Core stylesheets
mix.sass('resources/assets/src/vendor/styles/bootstrap.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/appwork.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-corporate.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-paper.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-paper-yg.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-air.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-cotton.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-twitlight.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-vibrant.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/theme-green.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/colors.scss', 'public/vendor/css', sassOptions)
    .sass('resources/assets/src/vendor/styles/uikit.scss', 'public/vendor/css', sassOptions)

// Core javascripts
mixAssetsDir('vendor/js/**/*.js', (src, dest) => mix.scripts(src, dest));

// Fonts
mixAssetsDir('vendor/fonts/*.css', (src, dest) => mix.copy(src, dest));
mixAssetsDir('vendor/fonts/*/*', (src, dest) => mix.copy(src, dest));


//service worker
//https://laravel-mix.com/extensions/workbox
const workboxConfig = {
    maximumFileSizeToCacheInBytes: 40000000,
    modifyURLPrefix: {
        '//': '/',
    },
    /* if the include is enabled , chunked javascript files form webpack are not
    include:[
        path.join(__dirname, 'public/img'),
        path.join(__dirname, 'vendor/js'),
        path.join(__dirname, 'vendor/fonts')
    ],
    */
    ignoreURLParametersMatching: [/.*/], // https://github.com/GoogleChrome/workbox/issues/1902
    // Define runtime caching rules.
    runtimeCaching: [{
        // Match any request that ends with .png, .jpg, .jpeg or .svg.
        urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
        // Apply a cache-first strategy.
        handler: 'StaleWhileRevalidate',
        options: {
            // Use a custom cache name.
            cacheName: 'images',
            // Only cache 50 images.
            expiration: {
                maxEntries: 200,
            },
        },
    }],
    cleanupOutdatedCaches: true
    //skipWaiting: true
};


/*
 |--------------------------------------------------------------------------
 | Entry point
 |--------------------------------------------------------------------------
 */

mix.js('resources/assets/src/entry-point.js', 'public')
    //.extract() //https://laravel-mix.com/docs/5.0/extract --> empty css files https://github.com/JeffreyWay/laravel-mix/issues/1914 The problem is solved in Mix v6 which now uses webpack 5.
    //.generateSW(workboxConfig) //https://laravel-mix.com/extensions/workbox


if (mix.inProduction()) {
    mix.version() // Use `laravel-mix-versionhash` for the generating correct Laravel Mix manifest file.
    //.versionHash() //
} else {
    mix.sourceMaps()
    if (Mix.isUsing('hmr')) {
        mix.disableNotifications();
    }
}

@daun
Copy link
Author

daun commented May 15, 2022

@speniti Are there plans for tackling this issue? Currently, the plugin has become unusable for any project with a custom public path. If the two suggested fixes above won't work, we can keep exploring options.

@daun
Copy link
Author

daun commented Dec 18, 2022

I've published a fork of this library to npm that fixes the issue with broken outputs paths of async chunks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants