Vite add assets path prefix / change assets path in compiled files - javascript

Could you tell me please, how to change how vite assets path is built, but only for compiled files?
I mean, for example, I have file index.html like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<script type="module" src="/src/main.js"></script>
</body>
</html>
and here I have script with src="/src/main.js"
When I compile it, I get src="/assets/index-c371877d.js"
I am making ESP32 webserver, and because of some internal moments I need to put compiled files in another folder, on SD card.
I can change output directory using vite.config.js, here I have:
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
outDir: "../../SD/modules/test", // test is project name
},
})
But the problem is, that compiled files have same relative path, while I need to have modules/%moduleName%/%relative path%
So instead of src="/assets/index-c371877d.js" I need src="module/test/assets/index-c371877d.js"
I tried to change vite assetsDir:
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
outDir: "../../SD/modules/test",
assetsDir: "modules/test"
})
Now it adds modules/test before path, but compiled files are put into outDir + assetsDir directory, what I don't want.
Tell me please, how could I just prepend necessary path data without changing real assets directory? Thank you in advance.

Solved, finally.
It was needed to provide base property for config
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
outDir: Config.modulesDirRelativePath + "/vue-project"
},
base: "/modules/vue-project"
})

Related

Expose a function from a webpack bundle

I'm trying to expose a function to a webpage, that can be called externally, or on window.load, or at anypoint.
DoThing.ts
import * as lib from "libs";
export default function DoAThingFunc():void{
console.log('Do a thing)'
}
This is then imported thing
ExposeDoThing.js
import DoAThingFunc from './DoThing'
window.exposeFunc = DoAThing
window.exposeFunc():
webpack 4 bundle
entry: {
main: './src/MainEntry.tsx',
popupcallback: './src/ExposeDoThing.js'
},
output: {
path: path.join(__dirname, outputDir + "/js"),
filename: '[name].js',
publicPath: "/js/",
library:'pclGlobal'
},
MyPage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pop up</title>
</head>
<body>
<script src="/js/vendor-main.js" type="text/javascript"></script>
<script src="/js/popupcallback.js" type="text/javascript"></script>
</body>
</html>
Nothing is being called, pclGlobal is undefined even though:
var pclGlobal=(window.webpackJsonppclGlobal=window.webpackJsonppclGloba...
is present in the output. And nothing is being called from the functions.
I just want the function DoAThingFunc() to fire when the script has loaded, what am I missing?
I think you need to expose your bundle as a library. check this link about output section in webpack config, and check the right way to do it.
Maybe a config like this: (pay attention to libraryExport attr)
module.exports = {
entry: './index.js',
output: {
path: './lib',
filename: 'yourlib.js',
libraryTarget: 'umd',
library: 'YourLibraryName',
umdNamedDefine: true,
libraryExport: 'default'
}
};
I noticed the vendor-main.js in my quoyted html example, except we don't have one in the weback entry and yet there is file output...
It looks like we used to have a vendors bundle, and then stopped but left the following the webpack.config.js
runtimeChunk: {
name: entrypoint => `vendor-${entrypoint.name}`
}
This has a weird effect. If your entry is not called main, then it wouldn't any execute anyexport default functions.

No prefetched files with preload-webpack-plugin

I have a question related to prefetching and preloading.
I have vue app and after build I receive double loaded files in my dist/index.html. You can see it below.
Moreover the "scripts" are not preloaded/prefetched. I do not know why. I have a plugin installed.
<head>
<title></title>
<link href=/app.128b43f14088f83cb6c0.js rel=preload as=script>
<link href=/chunk-vendors.128b43f14088f83cb6c0.js rel=preload as=script>
<div id=app></div>
<script src=/chunk-vendors.128b43f14088f83cb6c0.js></script>
<script src=/app.128b43f14088f83cb6c0.js></script>
vue.config.js
modules.export = {
configureWebpack: () => {
return {
devtool: 'source-map',
output: {
filename: '[name].[hash].js',
chunkFilename: '[name].[hash].js'
},
plugins: [
new PreloadWebpackPlugin(),
new CleanWebpackPlugin()
],
resolve: {
alias: {
styles: path.join(__dirname, 'src/assets')
}
}
}
}
}
I have vue app and after build I receive double loaded files in my dist/index.html.
Vue CLI already injects its own preload plugin, so your plugin is duplicating the preload/prefetch. Simply remove yours to resolve the duplication.
You should stick with the one already provided by Vue CLI, as it's modified to work with the Vue CLI toolchain. If you prefer to use your own for some reason, you could remove the built-in plugin with:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugins.delete('preload')
config.plugins.delete('prefetch')
}
}

How to properly split common dependencies with webpack4

I am having difficulty configuring webpack4 to properly bundle shared dependencies.
I have two pages in my application (Page1 and Page2). Both require bootstrap, jquery as well as a custom JavaScript app called core.
Page 2 requires the same but also a custom JavaScript application called my-app and also lodash.
Since my core app will be included in all pages, I want to have jquery and bootstrap in the same bundle.
Since lodash is only required for pages running my-app, I want to include that dependency in the my-app bundle.
So I setup my app like this:
webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
'core': './src/core/index.js',
'my-app': './src/my-app/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
alias: {
jquery: 'jquery/src/jquery',
}
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
],
mode: 'development',
}
page1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page1</title>
<script src="dist/core.bundle.js"></script>
</head>
<body>
<h1>Page1</h1>
<span id="test"></span>
</body>
<script>
$(document).ready(function() {
$('#test').text('jQuery Works!');
});
</script>
</html>
page2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page1</title>
<script src="dist/core.bundle.js"></script>
<script src="dist/my-app.bundle.js"></script>
</head>
<body>
<h1>Page2</h1>
<span id="test"></span>
</body>
<script>
$(document).ready(function() {
$('#test').text('jQuery Works!');
});
</script>
</html>
(Full project: https://github.com/LondonAppDev/webpack-split-example)
When I run npx webpack, it creates core.bundle.js and my-app.bundle.js, however both of these include jquery.
Is it possible to put all "global" dependencies in core.bundle.js?
Just one thing to remember here, with webpack 4 you don't add vendor scripts as an entry to your webpack.config, just real entry scripts to your application.
WP will create an optimized bundle output for your app using the default settings.
You have to add vendor cache group to your config, in order to extract jQuery, Lodash, Bootstrap,Popper into a separate bundle:
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /node_modules/,
name: "vendor",
chunks: "all",
enforce: true
}
}
}
},

Cannot GET / with webpack-dev-server

How come I am getting Cannot GET / in my browser? I think it is because my webpack-dev-server does not have a route to GET the bundled files.
devServer/server.js
import config from '../../webpack.config';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import open from 'open';
// template! https://github.com/webpack/webpack-dev-server/blob/master/examples/node-api-simple/server.js
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
contentBase: '../dist/',
stats: {
colors: true
}
});
server.listen(3000, '127.0.0.1' ,err => {
if (err) {
console.log(err);
} else {
console.log('Dev Server listening on port 3000!\n');
open("http://localhost:3000");
}
});
webpack.config.js
import webpack from "webpack";
export default {
entry: [
"./app/index"
],
devtool: "inline-source-map",
output: {
path: __dirname + "/app/dist/", // Note: Physical files are only output by the production build task `npm run build`.
publicPath: "/",
filename: "bundle.js"
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
],
module: {
rules: [
{ test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react']
}
}}
]
}
};
Project structure
On successful build a folder dist will be created inside the app folder which currently is not there.
Once the folder is created you can try by directly hitting the file path
http://localhost:3000/app/dist/yourfile
You can access your page via localhost:3000
When you access this path webpack dev server is searching for an index.html file to serve (like any other webserver). It can not find an index.html file because you have no index.html file. The index.html file is served from the static directory, which you have defined via property contentBase: '../dist/',.
but as I see you have no directory named dist and you have no index.html in this directory.
Your script is served from the public path, that is / in your config, so you have to reference this in your index.html
Solution:
Create directory dist and put an index.html file there with the following content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="/bundle.js"></script>
</body>
</html>
For more information read here:
https://webpack.github.io/docs/webpack-dev-server.html

Webpack publicPath don't work

I have a demo like this:
my webpack config:
module.exports = {
entry: './app.js',
output: {
filename: 'bundle.js',
path: './build',
publicPath: 'http://localhost:3000/'
},
module: {
rules: [{
test: /static\.html/,
use: 'file-loader'
}, {
test: /\.png/,
use: 'file-loader?name=[name].[ext]'
}, {
test: /\.css/,
use: 'file-loader?name=[name].[ext]'
}],
},
resolveLoader: {
modules: ['node_modules'],
}
}
this is my entry app.js:
import './static.html';
import './img.png';
import './index.css';
static.html:
<!DOCTYPE html>
<html>
<head>
<title>static</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="./index.css">
</head>
<body>
<img src="./img.png">
</body>
</html>
when i run npm run build, i got a build folder. I think the build/static.html should be
<img src="http://localhost:3000/img.png">
<link href="http://localhost:3000/index.css">
But, actually the build/static.html is the same as static.html. Both of the src of img and the href of link are not changed.
Any one knows why?
====
I have known the answer. Webpack publicPath just work for output file. So just the url in the bundle.js will be replaced.
The webpackHtmlPlugin will not resolve this problem, because this plugin will generate a html page with a script links to the output bundle.js that I don't need it.
To resolve this problem, I have wrote a custom loader to transform the html page output by the file-loader dynamicly.
The file-loader would not change the file. If you want a html file with the publicPath added, you should use html-webpack-plugin.

Categories

Resources