Webpack not loading partial files from the same root - javascript

I am compiling a javascript bundle with Webpack. I am specifiying a single file in my build task:
webpack({
entry: 'src/js/main.js',
output: { path: 'dist/js' }
}, function(e) {});
And then I am specifying some async packages in my bundle
require([ 'test.json' ], function() {});
Both the main bundle and the partial bundles compile into "dist/js/main.js", "dist/js/1.main.js", etc.
The main bundle loads from "localhost:8000/dist/js/main.js," but the async/partial dependencies are trying to load from "localhost:8000/1.main.js". Am I missing a critical piece of this?

You need to set the publicPath property, eg:
{
entry: 'src/js/main.js',
output: {
path: 'dist/js',
publicPath: '/dist/js/'
}
}
References:
output.publicPath

Related

Can you compile a TS file with webpack separately from Vue application?

So I have a Vue 3 + Typescript app. npm run build of course takes the app and compiles it into the dist folder so it can be deployed. I have a web worker typescript file that I would like to be compiled separately so that it ends up in the root of the dist folder with the name worker.js. Here is what I'm looking for:
dist
|- worker.js
src
|- worker.ts // This gets compiled to js file in dist folder
I tried doing this by using webpack's DefinePlugin in my vue.config.js like so:
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
entry: `${__dirname}/src/worker.ts`,
module: {
rules: [
{
test: /worker\.ts$/,
use: 'ts-loader',
exclude: /node-modules/
}
]
},
resolve: {
extensions: ['.ts']
},
output: {
filename: 'worker.js',
path: `${__dirname}/dist`
}
})
],
resolve: {
alias: {
vue$: 'vue/dist/vue.esm-bundler.js'
}
}
}
}
Unfortunately this doesn't work, npm run build just completely ignores the worker.ts file and it doesn't show up in the dist folder anywhere, not even as a chunk. Any suggestions? Or is what I'm wanting to do even possible? Thanks for any help!
I was able to get the desired result using esbuild. Now I can write my web worker in Typescript and use classes and functions from my Vue app. It also compiles lightning fast. I just added the node ./esbuild.js command to my npm run dev and npm run build scripts, and now it compiles to the public folder before the Vue app builds. Here is my esbuild.js file.
const esbuild = require('esbuild')
const { nodeExternalsPlugin } = require('esbuild-node-externals')
const config = {
entryPoints: ['./src/worker.ts'],
outfile: 'public/worker.js',
bundle: true,
minify: false,
logLevel: 'silent',
plugins: [nodeExternalsPlugin()]
}
esbuild.build(config).catch(() => process.exit(1))
Let me know if you have any questions, I'd be happy to help anyone out getting this working.

Vue.js / Webpack build "index.html" using a "static" subdomain for CSS and JS

I have a Vue.js project that is working fine in localhost.
But when I build and deploy to production, I need the static files (.css and .js) to be served on a "static" subdomain.
For example, my main URL:
https://www.example.com/index.html
The static assets will be:
https://static.example.com/css/app.50f83e17.css
https://static.example.com/js/chunk-vendors.6f495bf3.js
When I run "npm run build" Webpack build the "index.html" file loading like this:
<link href=/css/app.50f83e17.css rel=stylesheet>
But I need the href to be like this:
<link href=https://static.example.com/css/app.50f83e17.css rel=stylesheet>
How do I configure Vue.js or Webpack to build the "index.html" using a different subdomain for the CSS and JS?
To achieve this you would need to use webpack publicPath
You can configure webpack to build index.html using a different subdomain,
webpack.config.js
import webpack from 'webpack';
export default {
output: {
..
publicPath: 'https://static.example.com/js/',
},
};
npm run build Webpack build the "index.html" would have
..
..
<script type="text/javascript" src="https://static.example.com/js/chunk-vendors.6f495bf3.js"></script>
For css,
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: 'https://static.example.com/css/',
},
},
'css-loader',
],
},
],
},
};
You can also specify publicPath at runtime,
entry.js
__webpack_public_path__ = myRuntimePublicPath;
// rest of your application entry
Note: please consider adding a environment variable instead of hardcoding the asset CDN path, and pass the environment variable via npm scripts, alternately you can also define a global publicPath
var myRuntimePublicPath = 'https://static.example.com/js/'
and use it in the entry file (say entry.js) as displayed above.
refer: webpack publicPath and mini-css-extract-plugin publicPath
In case of using Vue Router
The base URL your application bundle will be deployed at publicPath (known as baseUrl before Vue CLI 3.3).
vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? 'https://static.example.com/js/'
: '/'
}
Vue Router
// override the base to hardcoded default value as it gets the value from publicPath
base: '/'
This will allow subdomain for javaScript bundle of vuejs build.

debug typescript (.ts) files in brower from JS files generated through webpack

I have just started learning ASP.NET Core and basics of TypeScript. I have the following object class:
export class StoreCustomer {
constructor(private firstName: string, private lastName: string) {
}
public ShowName() {
alert(this.firstName + " " + this.lastName);
}
}
And the following main.ts class:
import { StoreCustomer } from "./storecustomer";
let a = new StoreCustomer("FirstName", "LastName");
a.ShowName();
Both TS files are present in wwwroot folder. When I reference the trans piled JS files in my HTML page, I get the error saying exports is not defined. I learned that you need to use a module loader to solve this issue, so I installed webpack in my project through NPM. webpack again generates new JS files which when referenced in my HTML page, I get the desired output. But the problem is, since the TS files are not in the same directory and I cannot generate the js files in the same folder as the TS files, I am not able to debug the TS files in the browser. How can I debug TS files from JS files generated through webpack?
EDIT:
My webpack.config.js file:
var path = require('path');
module.exports = {
entry: {
main: './wwwroot/ts/main.js',
storecustomer: './wwwroot/ts/storecustomer.js',
},
output: {
path: path.resolve(__dirname, './wwwroot/scripts'),
filename: '[name].js'
},
devtool: "source-map",
};
In your webpack configuration, you are starting from the .js files, that is the reason that the .map files point to the .js files.
If you want to see the TypeScript files, you need to configure your webpack to use ts-loader (https://webpack.js.org/guides/typescript/):
For example:
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]

Webpack: load js modules dynamically from a URL at runtime

I am currently working on a library which should dynamically load a JavaScript from a remote host and instantiate that.
I am writing the library in TypeScript and my plan is to use Webpack as a bundler.
On another host (remote system) runs a provider which should serve JavaScript code (see here: https://stubs.d-koppenhagen.de/stubs/SimpleStub.js).
The library will dynamically resolve "Identitys" via Webfinger. These Identitys represented by an object and they having a property pointing to a "Stub Provider" which will serve JavaScript code (the link I mentioned before). My library should load this script during runtime (s the library don't know the target for this stubs before) and should use it.
currently my webpack.config.js looks like the following:
var path = require('path');
var webpack = require('webpack');
var WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PATHS = {
src: path.join(__dirname, './src'),
build: path.join(__dirname, './dist')
};
module.exports = {
entry: {
wonder: PATHS.src + '/wonder'
},
output: {
path: PATHS.build,
filename: '[name].js',
library: 'Wonder',
libraryTarget: 'umd'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
},
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new WebpackBuildNotifierPlugin()
]
};
And here is a part of the library code:
require.ensure([], function() {
require(localMsgStubUrl);
});
When I am now including the bundled library in an example app, I will get the following error:
Error: loading chunk failed
So is there a way to tell webpack not to bundle the code which is required from a external resource loaded from a URL so that I can use that code like it is?
I don't want to tell webpack the URL statically in a config as maybe other stubs I am loading are located on a different target.
Thanks in advance for your help!

How to add a js file with webpack?

I was reading this webpack tutorial:
https://webpack.github.io/docs/usage.html
It says it bundles the src files and node_modules. If I want to add another .js file there, how can I do this? This is a thirdpartyjs file that is not part of the source and not part of the node_modules files. This is my current webpack.config.js:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./app/app.js'
],
output: {
path: path.resolve(__dirname, "dist"),
publicPath: "/dist/",
filename: "dist.js",
sourceMapFilename: "dist.map"
},
devtool: 'source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
}),
],
module: {
loaders: [{
loader: 'babel',
exclude: /node_modules/
}]
},
devServer: {
inline: true
},
node: {
fs: "empty"
},
watch: false
}
The start point for code is the entry field in config. In your config entry point is the list of files. Webpack gets all, resolve their dependencies and output in one file.
You have two options for adding third party script:
add the file path to entry list before app.js
require this file from app.js
In response to Dmitry's answer:
add the file path to entry list before app.js
This has the effect that you will get a bundled .js file for each entry point, which you might not want.
require this file from app.js
You might not have access to app.js if it is written dynamically, or for whatever reason you might not want to edit app.js.
Another option:
You can use webpack-inject-plugin to inject any JS code as string into the resulting .js bundle created by webpack. This way you can read the File you want to inject as a string (e.g. fs.readFile in nodejs) and inject it with the plugin.
Another solution but without using any extra plugins:
//Webpack.config.js
entry: {
main: './src/index',
/**
/* object is passed to load script at global scope and exec immediately
/* but if you don't need then simply do:
/* myCustomScriptEntry: './src/myCustomScript'
*/
myCustomScriptEntry: {
import: './src/myCustomScript',
library: {
name: 'myCustomScriptEntry',
type: 'var',
},
},
},
new HtmlWebpackPlugin({
template: './public/index.html',
excludeChunks: ['myCustomScriptEntry'], //exclude it from being autoreferenced in script tag
favicon: './public/favicon.svg',
title: 'Alida',
}),
and
//index.html
<script type="text/javascript" src="<%= compilation.namedChunks.get('myCustomScriptEntry').files[0] %>"></script>

Categories

Resources