简体   繁体   中英

Vanilla.js Client Side Router + Webpack --> Ressource blocked (due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff))

After using Webpack for lazy-loading (green coding) my vanilla.js client side router fails on advanced routes (.../blog/2 as one example) because the necessary.js file is blocked as described in the title. By using a button-link everything is fine ( data-btnref="navlink" ) but by direct enter the address in the browser it replies with the error.

GET http://localhost:3000/blog/main8f1360562bd664fccb25.js [HTTP/1.1 404 Not Found 3ms]

The resource from “http://localhost:3000/blog/main8f1360562bd664fccb25.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).

Loading failed for the <script> with source “http://localhost:3000/blog/main8f1360562bd664fccb25.js”.

I know that this is an advanced question but maybe some professional coder likes my "self-learned" approach to handle things and help me out. I cleaned my approach as far as i can.

code: index.html:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Client side routing with vanilla.js + webpack lazy load</title>
</head>
<body>
    <header>
        <nav id="nav">
            <a href="/" data-btnref="navlink">Home</a>
            <a href="/blog" data-btnref="navlink">Blog</a>
            <a href="/contact" data-btnref="navlink">Contact</a>
        </nav>
    </header>
    <main id="main"></main>
</body>
</html>

index.js:

import { navigateTo } from "./js/functionality/router.js";
document.addEventListener("DOMContentLoaded", () => {
    document.body.addEventListener("click", e => {
        switch (e.target.dataset.btnref) {
            case ("navlink"):
                e.preventDefault();
                navigateTo(e.target.href, "navlink");
                break;
            default:
                break;
        };
    });
    navigateTo(location.pathname);
});

router.js:

const Home = () => import('../views/home');
const Blog = () => import('../views/blog');
const Blogpost = () => import('../views/blogpost');
const Contact = () => import('../views/contact');
const Login = () => import('../views/login');
const PageNotFound = () => import('../views/404');
export const navigateTo = (url, btnref) => {
    switch (btnref) {
        case ("navlink"):
            const raw_url = url.split("/");
            if (raw_url.length > 4) {
                const corrected_url = "/blog/" + raw_url[raw_url.length - 1];
                history.pushState(null, null, corrected_url);
            } else {
                history.pushState(null, null, url);
            };
            break;
        default:
            break;
    };
    router();
};
const router = async () => {
    const routes = {
        "/": Home,
        "/blog": Blog,
        "/blog/:id": Blogpost,
        "/contact": Contact,
        "/login": Login,
        "/404": PageNotFound,
    };
    let match;
    if (routes[location.pathname]) {
        match = await routes[location.pathname]().then(m => { return m.default() });
    } else {
        if (location.pathname.split("/")[1] === "blog") {
            const id = location.pathname.split("/")[2];
            match = await routes["/blog/:id"]().then(m => { return m.default(id) });
        } else {
            match = await routes["/404"]().then(m => { return m.default(`${location.pathname}`) });
        };
    };
    document.getElementById('main').innerHTML = match;
};
window.addEventListener("popstate", router);

webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
    mode: 'development',
    entry: {
        main: path.resolve(__dirname, 'src/index.js'),
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name][contenthash].js',
        clean: true,
        assetModuleFilename: '[name][ext]',
    },
    devtool: 'source-map',
    devServer: {
        static: {
            directory: path.resolve(__dirname, 'dist'),
        },
        port: 3000,
        open: true,
        hot: true,
        compress: true,
        historyApiFallback: true
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader',
                ],
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }, 
            {
                test: /\.(svg|png|jpg|jpeg|gif)$/i,
                type: 'asset/resource',
            },
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Webpack App',
            filename: 'index.html',
            template: 'src/template.html',
        }),
        new BundleAnalyzerPlugin(),
    ]
}

The solution to this issue is to add <base href="/" /> inside the <head> of the template.html. This fixed the 404 - error:

The resource from “http://localhost:3000/blog/main8f1360562bd664fccb25.js” ....

to the correct path:

http://localhost:3000/main8f1360562bd664fccb25.js

This problem is also known as "Webpack chunks fail to load in nested routes #333 - GitHub".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM