简体   繁体   中英

Webpack relative paths to files and multi slash paths in routes

Recently i encountered an issue with building multi slash routing paths for my react application configured with webpack and nodejs on the backend.

Issue started when i created following path inside routing:

// header
{[1, 2, 3, 4, 5].map((id) => (
    <NavLink to={`/product/${id}`} className={({ isActive }) => (isActive ? 'active' : undefined)} key={`product-${id}`}>
        Product
        {id}
    </NavLink>
))}

// router
<Routes>
    <Route path="/product/:id" element={<Product />} />
</Routes>

The path itself is working correctly when accessed via link but when accessed from nodejs (refresh or type url directly) it is failing because its trying to load js and css files with following paths:

  • Refused to execute script from 'http://localhost:8080/product/js/main.2265f70c.js'
  • Refused to apply style from 'http://localhost:8080/product/css/style.2265f70c.css'

So its trying to load css and js relative to /products path.

My webpack config:

const htmlPlugin = new HtmlWebPackPlugin({
    template: './src/index.html',
    filename: 'index.html',
});

const miniCssExtractPlugin = new MiniCssExtractPlugin({
    filename: 'css/style.[fullhash:8].css',
    chunkFilename: 'css/[id].style.[fullhash:8].css',
});

module.exports = {
    ...
    output: {
        filename: 'js/main.[fullhash:8].js',
    },
    module: {
        rules: [
            ...
            {
                test: /\.(json)$/,
                loader: 'file-loader',
                type: 'javascript/auto',
                options: {
                    name: 'translations/[name].[ext]',
                },
            },
            {
                test: /\.(png|jpg|jpeg|gif|ico|svg|eot|ttf|woff|woff2)$/,
                type: 'asset',
                generator: {
                    filename: 'assets/[name].[hash][ext]',
                },
                parser: {
                    dataUrlCondition: {
                        maxSize: 20 * 1024, // 20kb
                    },
                },
            },
        ],
    },
    devServer: {
        historyApiFallback: {
            rewrites: [{ from: /^\/$/, to: '/index.html' }],
        },
    },
};

my nodejs dev server:

const express = require('express');
const path = require('path');
const config = require('./config');

const app = express();

app.use(express.static(path.join(__dirname, 'dist'), {
    maxage: '30d',
}));

app.use('*', express.static(path.join(__dirname, 'dist/index.html')));

app.listen(config.port, () => {
    console.log(`Listening on :${config.port}`);
});

My first idea was to replace relative paths with absolute ones in webpack configuration but that action causes this error:

[webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
 - configuration.output.filename: A relative path is expected. However, the provided value "/js/main.[fullhash:8].js" is an absolute path!
Please use output.path to specify absolute path and output.filename for the file name.

What is the proper way / good practice of dealing with it, so multi slash url is just virtual and not actually / literally considered?

  • nodejs v16.15.0
  • webpack v5.74.0
  • react v18.2.0

Ok so i was able to solve the problem by modifying webpack output configuratoin:

output: {
    publicPath: '/', // this is the fix
    filename: 'js/main.[fullhash:8].js'
},

After adding publicPath: '/' it started to work properly (files are loaded from root, while virtual locations are routed correctly)

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