'dynamic <base> tag based on window object
I need to set a base tag based on document.location
I'm using webpack5 and react.
this is my webpack config
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const packageDirName = process.cwd();
const paths = {
src: path.resolve(packageDirName, "src"),
dist: path.resolve(packageDirName, "../../dist"),
};
module.exports = {
entry: paths.src,
output: {
filename: "main.js",
path: paths.dist,
clean: true,
// publicPath: '/', //need to use it only on dev.
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
rootMode: "upward",
},
},
},
{
test: /\.scss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{test: /\.(jpg|jpeg|png|woff|woff2|eot|ttf|svg)$/,loader: 'url-loader'}
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin(getEnvVars("npm_package_version", "API_BASE_URL")),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public/index.html"),
favicon: path.resolve(__dirname, "public/favicon.ico"),
inject: true,
}),
],
devServer: {
historyApiFallback: true,
hot: true,
open: true,
// ...
},
};
and on the index.html I added the following code it tweak the base tag (inside )
<script type="text/javascript">
const baseURL = document.location.href.includes('/me') ? `${document.location.href.split('/me')[0]}/me/` : '/';
console.log('baseURL', baseURL);
const baseDirEl = document.createElement('base');
baseDirEl.setAttribute('href', baseURL);
document.getElementsByTagName('head')[0].appendChild(baseDirEl);
</script>
webpack is injecting this in index.html <script defer src="main.js"></script>
the main.js is fetched twice maybe it was triggered before the tag.
- for this link: http://example.com/me
- http://example.com/main.js - thats not
- http://example.com/me/main.js -thats ok
- http://example.com/en/main.js - thats not
- http://example.com/en/me/main.js - thats ok
- http://example.com/en/me/x/y/main.js - thats not
- http://example.com/en/me/main.js - thats ok
is there a way to avoid the first bundle fetch ? until my scripts finishes to generate the base tag ? or if there is a better way to tackle it ?
thanks.
Solution 1:[1]
Assuming you have a server that renders your html file.
You can simplify the solution using webpack's publicPath attribute.
My trick to inject a ejs variable, and change it's value when I render the HTML.
// webpack.config.js
const isDev = process.env.NODE_ENV === 'development';
module.exports = {
entry: paths.src,
output: {
filename: "main.js",
path: paths.dist,
clean: true,
publicPath: isDev ? '/': '/<%= lng %>me/',
// -----------------------^ this is the trick
},
...
}
Then when you render the html on you server, pass lng param which the value will be en/ or nothing if there is no language.
// server.js
var express = require('express');
var app = express();
// set the view engine to ejs
app.set('view engine', 'ejs'); // define ejs
// index page
app.get('/', function (req, res) {
const lng = req.lng ? `${req.lng}/` : '';
res.render('pages/index', {
lng,
});
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | felixmosh |
