How to configure webpack dev server to serve extensionless files as 'text/html' - vue.js

Problem
In development, serving files without an extension (e.g. /region) are being served with mimetype `application/octet-stream'. Desired state is to serve these with mimetype 'text/html'.
Context
Writing a multipage application using Vue3. Upgraded #vue/cli and that upgraded webpack from 4 to 5. Serving extensionless files did not have this issue using webpack4's dev server.
In production this isn't a problem as the webserver there is configured to serve these files with the 'text/html' mimetype.
Dependency versions
node 16.13.0, webpack 5.64.1, webpack-dev-middleware 5.2.1, #vue/cli 5.0.0-rc.0
Webpack5 config
entry: {
region: [
'/home/alice/workspace/vapp/src/pages/region/main.js'
],
plugins: [
/* config.plugin('html-region') */
new HtmlWebpackPlugin(
{
title: 'Region',
scriptLoading: 'defer',
templateParameters: function () { /* omitted long function */ },
chunks: [
'chunk-vendors',
'chunk-common',
'region'
],
template: 'src/pages/region/region.html',
filename: 'region'
}
),
]
Attempts
Supplying custom extension to mime type mapping works for custom extensions just fine, e.g. 'foo': 'text/html' will serve region.foo as html. However, there doesn't appear to be a way to specify a mime type for files without an extension. None of the these mimeTypes entries have been successful.
// webpack.config.js
devServer: {
devMiddleware: {
mimeTypes: {
'': 'text/html',
false: 'text/html',
null: 'text/html',
default: 'text/html',
}
}
}

Related

The debugger adapter not works after vsce package

I developed a debug extension which uses an external js debugger adapter. I put the js file to the bin directory looks like this.
rootDir
--bin
----adapter.js
And I used it like this in my development environment.
{
"label": "ThingIO Debugger",
"program": "./bin/adapter.js",
"runtime": "node",
"type": "thingio-debug"
}
The code works well in my development mode, but when I packaged it to a .vsix file and install to another machine, it failed immediately.
The webpack file is below
//#ts-check
'use strict';
const path = require('path');
//#ts-check
/** #typedef {import('webpack').Configuration} WebpackConfig **/
/** #type WebpackConfig */
const extensionConfig = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
// modules added here also need to be added in the .vscodeignore file
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
};
module.exports = [ extensionConfig ];
And the vscode:prepublish command is webpack --mode production --devtool hidden-source-map
I think it looks like the debugger adapter program is not found. So I checked the ~/.vscode/extensions, and the adapter js file exists in the right path.
Now I'm very confused about what wrong is with the extension. Maybe the path is wrong or the webpack did not compile the right file in some situation?
Can anyone give some solution or suggestion about this?

Workbox webpack plugin is not loading assets (.js) from cache after installed

I am trying to set up a PWA for an app in Laravel (5.8) with vuejs (2.5).
This is the configuration I have in mix.js:
...
mix.js('resources/js/app.js', 'public/js')
.generateSW({
// Define runtime caching rules.
runtimeCaching: [{
// Match any request that ends with .png, .jpg, .jpeg or .svg.
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
// Apply a cache-first strategy.
handler: 'CacheFirst',
options: {
// Use a custom cache name.
cacheName: 'images',
// Only cache 10 images.
expiration: {
maxEntries: 10,
},
},
}],
skipWaiting: true
})
.vue()
.copy('node_modules/lodash/lodash.min.js', 'public/js')
.copy('./resources/manifest.json', 'public/dist/manifest.json')
.copy('./resources/icons', 'public/dist/')
.extract(['vue'])
.webpackConfig({
output: {
filename: '[name].js',
chunkFilename: `[name].chunk.[contenthash:8].js`,
path: path.join(__dirname, 'public/dist'),
publicPath: '/dist/'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js',
'variables': path.resolve('resources/sass/_variables.scss')
}
},
plugins: [
new webpack.ContextReplacementPlugin(
/moment[\/\\]locale$/,
/(en|es)$/
),
]
})
.options({
processCssUrls: false,
});
...
The service worker was installed correctly and the first time it loads it caches my assets.
But the next calls I make (reload the page) don't use that cache and reload the assets from the network.
However, what I am looking for is a quick initial load after the PWA is installed and this is not happening.
I have done this before with Angular and the PWA module and the assets are loaded from cache, and if there are changes, they are updated later, which makes the initial load of the application very fast.
Can someone help me with this?
In the end I ended up using workbox-cli with this setup:
// workbox.config.js
module.exports = {
"globDirectory": "public/",
"globPatterns": [
"**/*.{js,css,ico,woff2,webmanifest}",
"**/images/icons/*",
"**/images/*",
],
// 15mb max file size
maximumFileSizeToCacheInBytes: 15 * 1024 * 1024,
globIgnores: [
'**/mix-manifest.json',
'**/js/{manifest,vendor}.js',
'**/js/chunks/*',
],
"swDest": "public/service-worker.js",
"swSrc": "resources/sw-offline.js"
};
And running this at the end of my npm run prod
workbox injectManifest workbox.config.js
All credit to this repository:
https://github.com/aleksandertabor/flashcards

How to run Nuxt2 serverMiddleware with pm2

I have a simple Nuxt ssr app with a serverMidlleware handling one api endpoint (/api/contact). To deploy the app I am using pm2.
Running the app in development and in production (locally without pm2) everything works fine. Deploying it on a basic ubuntu server using pm2, the api endpoint becomes unreachable (404 not found).
As pointed out here, the middleware is not included in the .nuxt build. So, I made sure to copy the api directory (where my middleware is located) too.
for pm2 deployment, ecosystem.config.js:
module.exports = {
apps: [
{
name: 'App',
exec_mode: 'cluster',
instances: 'max',
script: './node_modules/nuxt/bin/nuxt.js',
args: 'start'
}
]
}
and inside nuxt.config.js:
serverMiddleware: [
{ path: '/api/contact', handler: '~/api/contact.js' }
]
As only the deployment via pm2 fails, I assume the other files are not of interest. I am assuming this must be related to some sort of pm2 config to find the api folder.
Following my answer here solved the issue here too.
You probably had something missing in your nuxt.config.js file
export default {
ssr: true,
target: 'server',
modules: [
'#nuxtjs/axios',
],
serverMiddleware: [
{ path: '/api', handler: '~/server-middleware/rest.js' },
],
}

Vue multiple pages with a webworker

Using vue cli 3 I have a project using harp.gl where I need a webworker to decode map tiles.
My vue.config.js has the following:
module.exports = {
pages: {
app: {
entry: './src/main.js',
filename: 'index.html',
title: 'Contextual Map HARP.GL/Vue',
},
decoder: {
target: "webworker",
entry: "./src/decoder.js",
output: {
filename: "[name].bundle.js",
},
devtool: 'source-map',
...
When I run this I have both the app and the decode.js running as a webworker of type "script" (when inspecting it using Chrome).
However, after upgrading to vue cli 4 the above code does not work, as inspecting it using Chrome the webworker type is text/html and it appears to serve the default index.html. It alomst as if the type: "webworker" is not working the same as with version 3.
I am at loss as how to fix this, the move from vue cli 3 to 4 changed something, but I cannot figure out what to change.

Webpack, Scss - add cdn server path before compilation

How do I add a cdn path variable into the styles.scss before compilation? I have a webpack 4 configuration that works fine for JS. The JS/CSS files are loaded correctly from the desired cdn url.
What I want to achieve is, that the project running on localhost will use a different cdn url for images/icons/fonts than the same web running on production.
My webpack config has these lines for setting the cdn domain:
if (process.env.NODE_ENV === 'production') {
webUrl = 'https://cdn.project.com/';
}
else if (process.env.NODE_ENV === 'development') {
webUrl = 'http://localcdn.localhost/';
}
This code works well for JS/CSS files, but CSS always loads backgrounds/fonts using a relative path, which of course is the main domain and not the cdn.
Maybe just open the styles.scss and update the file manually before webpack compilation? Isn't there a better way?
After hours of trial and error I found this solution for webpack 4. It may help someone trying to solve the same issue.
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options : {
url : false,
sourceMap: devMode
}
},
{
loader: 'sass-loader',
options : {
processCssUrls : false,
sourceMap: devMode,
data : "$cdnFolder: 'http://cdn.myweb.net/';"
}
}
],
},
This is a part of webpack.config.js, in the section:
module : {
rules : {
This configuration makes the scss variable $cdnFolder available in every scss file. CDN link can be changed based on the current mode dev/prod/stage.
For webpack 5, the config changed a little:
{
loader: 'sass-loader',
options : {
additionalData : "$cdnFolder: '" + cdnUrl + "';"
}
}