Vue2 source maps referencing vue.runtime.esm.js file, not component file - javascript

Maybe I'm misinterpreting what source maps should do in a Vue app, but shouldn't I get the *.vue file line number where the error is occurring? I always get a refernce to a line number in a vue.runtime.esm.js file. It references the component, but the line number in the component file would be more helpful. Do I need to install additional source map modules?
My vue.config is below:
module.exports = {
assetsDir: "",
publicPath: "/",
css: {
sourceMap: true,
loaderOptions: {
sass: {
sassOptions: {},
},
},
},
configureWebpack: (config) => {
if (process.env.NODE_ENV === "development") {
config.devtool = "eval-source-map";
config.output.devtoolModuleFilenameTemplate = (info) =>
info.resourcePath.match(/^\.\/\S*?\.vue$/)
? `webpack-generated:///${info.resourcePath}?${info.hash}`
: `webpack-yourCode:///${info.resourcePath}`;
config.output.devtoolFallbackModuleFilenameTemplate =
"webpack:///[resource-path]?[hash]";
}
},
};
This also doesn't work:
configureWebpack: (config) => {
config.devtool = "source-map";
},

I had to use 'cheap-module-source-map' instead of 'eval-source-map'. In the end it would look like this:
configureWebpack: (config) => {
if (process.env.NODE_ENV === "development") {
config.devtool = "cheap-module-source-map";
[...]
}
},

Related

Nextjs config for JSX file type

I have created an Next 13 application where i have installed an package #viral-loops/widgets
Once the package is installed and when i run the application i am getting the following error
error - ./node_modules/#viral-loops/widgets/dist/react/Widget.jsx
Module parse failed: Unexpected token (34:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| return (
> <>
| {props.ucid ? (
| <form-widget ucid={props.ucid} popup={props.popup} />
Here is my next.config.js
module.exports = {
webpack(config, { isServer }) {
const prefix = config.assetPrefix ?? config.basePath ?? '';
config.module.rules.push(
{
test: /\.svg$/,
use: ['#svgr/webpack', 'url-loader'],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
},
],
},
{
test: /\.(mp4|webm|mov|ogg|swf|ogv)$/,
use: [
{
loader: require.resolve('file-loader'),
options: {
publicPath: `${prefix}/_next/static/videos/`,
outputPath: `${isServer ? '../' : ''}static/videos/`,
name: '[name]-[hash].[ext]',
},
},
],
},
);
return config;
},
images: {
disableStaticImages: true,
remotePatterns: [
{
protocol: 'https',
hostname: 'images.ctfassets.net',
pathname: '**',
},
],
},
sassOptions: {
includePaths: [
path.join(__dirname, 'styles'),
path.join(__dirname, 'styles/variables.scss'),
],
prependData: '#import "./styles/variables.scss";',
},
compilerOptions: {
baseUrl: '.',
paths: {
'#/components/*': ['components/*'],
},
},
};
I have tried setting up babel-loader like below in the next.config.js webpack
module.exports = {
webpack(config, { isServer }) {
const prefix = config.assetPrefix ?? config.basePath ?? '';
config.module.rules.push(
**{test: /\.(js|jsx)$/, use: 'babel-loader'}**,
Which returns a new error like below
Syntax error: Support for the experimental syntax 'jsx' isn't currently enabled (34:5):
32 |
33 | return (
> 34 | <>
| ^
35 | {props.ucid ? (
36 | <form-widget ucid={props.ucid} popup={props.popup} />
37 | ) : null}
Add #babel/preset-react (https://github.com/babel/babel/tree/main/packages/babel-preset-react) to the 'presets' section of your Babel config to enable transformation.
I am not sure where i have to add the #babel/preset-react in Nextjs application.
Next.js is not able to transpile .jsx/css/scss files from node_modules directory.
You can use next-transpile-modules. However, it is deprecated.
Since it is only one component that has this issue. You can create copy that component inside components' directory in your project root and use that component.
// #components/Widget
import * as React from "react";
import { useEffect } from "react";
export default function Widget(props) {
function loadViralLoops() {
const SCRIPT_SRC = "https://app.viral-loops.com/widgetsV2/core/loader.js";
const scriptExists = document.head.querySelector(
`script[src="${SCRIPT_SRC}"]`
);
if (scriptExists) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = SCRIPT_SRC;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
useEffect(() => {
loadViralLoops().then(() => {
const ViralLoops = globalThis["ViralLoops"];
console.debug("[VL] -> load ViralLoops script", ViralLoops);
});
}, []);
useEffect(() => {
console.debug("[VL] -> set props.ucid", props.ucid);
}, ["[VL] -> set props.ucid", props.ucid]);
return (
<>
{props.ucid ? (
<form-widget ucid={props.ucid} popup={props.popup} />
) : null}
</>
);
}
Widget.defaultProps = {};
I have done the following to make the viral-loop widget to work in Next.js.
To Integrate ViralLoop with Next.js application install the below package
yarn add #viral-loops/widgets
Install babel/preset-react
Yarn add #babel/preset-react --save-dev
Once the installation is complete go to Next.config.js and add the following snippet to transpile JSX
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-react'],
},
},
},
Once the above steps are done the unexpected token issue was fixed but to import the widget i have to use the dynamic import like below
import dynamic from 'next/dynamic';
const ViralLoopsWidget: any = dynamic(() => import('#viral-loops/widgets/dist/react').then((mod) => mod.ViralLoopsWidget), {ssr: false});
If the dynamic import is not needed then we can use the same inside an useEffect which will be called only on the client side render not on server side render
useEffect(() => {
const viralLoopInit = async () => {
const viralLoop = await import('#viral-loops/widgets/dist/react');
console.log('viralLoop is', viralLoop);
console.log('viralLoop1 is', await viralLoop.getCampaign());
}
viralLoopInit();
}, []);
Try Creating a file .babelrc at the project level, and add this config and install added deps,
{
"presets": ["next/babel", "#babel/preset-react"],
"plugins": ["#babel/plugin-transform-react-jsx"]
}

migrate from webpack to vite with vuejs for chrome extension project

I am working on a chrome extension using vuejs currently i have a ready project to start with but it is with webpack.
In the webpack I have multi-entry points some of which lead to generating HTML files and others with javascript only.
with webpack it is clear what is the inputs and how they will be as output in Vite i tried but there is a lot of plugins outdated that work with vuejs 3
this link contains the project
https://stackblitz.com/edit/vue-v83gga
my webpack file is :
const path = require("path");
const fs = require("fs");
// Generate pages object
const pages = {};
function getEntryFile(entryPath) {
let files = fs.readdirSync(entryPath);
return files;
}
const chromeName = getEntryFile(path.resolve(`src/entry`));
function getFileExtension(filename) {
return /[.]/.exec(filename) ? /[^.]+$/.exec(filename)[0] : undefined;
}
chromeName.forEach((name) => {
const fileExtension = getFileExtension(name);
const fileName = name.replace("." + fileExtension, "");
pages[fileName] = {
entry: `src/entry/${name}`,
template: "public/index.html",
filename: `${fileName}.html`,
};
});
const isDevMode = process.env.NODE_ENV === "development";
module.exports = {
pages,
filenameHashing: false,
chainWebpack: (config) => {
config.plugin("copy").use(require("copy-webpack-plugin"), [
{
patterns: [
{
from: path.resolve(`src/manifest.${process.env.NODE_ENV}.json`),
to: `${path.resolve("dist")}/manifest.json`,
},
{
from: path.resolve(`public/`),
to: `${path.resolve("dist")}/`,
},
],
},
]);
},
configureWebpack: {
output: {
filename: `[name].js`,
chunkFilename: `[name].js`,
},
devtool: isDevMode ? "inline-source-map" : false,
},
css: {
extract: false, // Make sure the css is the same
},
};
i finally find out a solution for it as a pre-build template by vitesse written with typescript
https://github.com/antfu/vitesse-webext
in short answer if you want to have multiple entries of HTML files you can add them to the original vite.config.js file
regarding the content.ts file, it needs a different vite.config.content.ts file and we have to call it when we build the project like this
vite build && vite build --config vite.config.content.ts
regarding the vite.config.ts file, the code will be like this written in typescript
/// <reference types="vitest" />
import { dirname, relative } from 'path'
import type { UserConfig } from 'vite'
import { defineConfig } from 'vite'
import Vue from '#vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import WindiCSS from 'vite-plugin-windicss'
import windiConfig from './windi.config'
import { isDev, port, r } from './scripts/utils'
export const sharedConfig: UserConfig = {
root: r('src'),
resolve: {
alias: {
'~/': `${r('src')}/`,
},
},
define: {
__DEV__: isDev,
},
plugins: [
Vue(),
AutoImport({
imports: [
'vue',
{
'webextension-polyfill': [
['*', 'browser'],
],
},
],
dts: r('src/auto-imports.d.ts'),
}),
// https://github.com/antfu/unplugin-vue-components
Components({
dirs: [r('src/components')],
// generate `components.d.ts` for ts support with Volar
dts: r('src/components.d.ts'),
resolvers: [
// auto import icons
IconsResolver({
componentPrefix: '',
}),
],
}),
// https://github.com/antfu/unplugin-icons
Icons(),
// rewrite assets to use relative path
{
name: 'assets-rewrite',
enforce: 'post',
apply: 'build',
transformIndexHtml(html, { path }) {
return html.replace(/"\/assets\//g, `"${relative(dirname(path), '/assets')}/`)
},
},
],
optimizeDeps: {
include: [
'vue',
'#vueuse/core',
'webextension-polyfill',
],
exclude: [
'vue-demi',
],
},
}
export default defineConfig(({ command }) => ({
...sharedConfig,
base: command === 'serve' ? `http://localhost:${port}/` : '/dist/',
server: {
port,
hmr: {
host: 'localhost',
},
},
build: {
outDir: r('extension/dist'),
emptyOutDir: false,
sourcemap: isDev ? 'inline' : false,
// https://developer.chrome.com/docs/webstore/program_policies/#:~:text=Code%20Readability%20Requirements
terserOptions: {
mangle: false,
},
rollupOptions: {
input: {
background: r('src/background/index.html'),
options: r('src/options/index.html'),
popup: r('src/popup/index.html'),
},
},
},
plugins: [
...sharedConfig.plugins!,
// https://github.com/antfu/vite-plugin-windicss
WindiCSS({
config: windiConfig,
}),
],
test: {
globals: true,
environment: 'jsdom',
},
}))
the important part of it is this
vite.config.ts
...
build: {
outDir: r('extension/dist'),
emptyOutDir: false,
sourcemap: isDev ? 'inline' : false,
// https://developer.chrome.com/docs/webstore/program_policies/#:~:text=Code%20Readability%20Requirements
terserOptions: {
mangle: false,
},
rollupOptions: {
input: {
background: r('src/background/index.html'),
options: r('src/options/index.html'),
popup: r('src/popup/index.html'),
},
},
},
...
Thank you to anyone who tried to help and I hope this will be helpful to others
Regards

How to configure craco to use jsx?

I am using craco and trying to figure out how to configure jsx. I keep getting the following error
Support for the experimental syntax 'jsx' isn't currently enabled (4:17):
They suggest that I add `babel/preset-react or use #babel/plugin-syntax-jsx to the plugin section to enable parsing but I'm unsure how to do that.
To clarify, I am trying to use a src folder outside the root of my react-app
craco.config.js
module.exports = {
webpack: {
alias: {},
plugins: {
add: [] /* An array of plugins */,
remove:
[] /* An array of plugin constructor's names (i.e. "StyleLintPlugin", "ESLintWebpackPlugin" ) */,
},
configure: {
/* Any webpack configuration options: https://webpack.js.org/configuration */
},
configure: (webpackConfig, { env, paths }) => {
console.log("WEBPACK");
console.log(webpackConfig);
webpackConfig.entry =
"C:\\Users\\danie\\Desktop\\Code\\JS\\npm_packages\\source\\src\\index.js";
return webpackConfig;
},
},
babel: {
presets: [],
plugins: [],
loaderOptions: (babelLoaderOptions, { env, paths }) => {
console.log("BABEL");
console.log(babelLoaderOptions);
return babelLoaderOptions;
},
},
};
Figured out my issue by adding the preset to my config file
craco.config.js
babel: {
presets: ['#babel/preset-react'],
// plugins: [],
loaderOptions: (babelLoaderOptions, { env, paths }) => {
console.log("BABEL");
console.log(babelLoaderOptions);
return babelLoaderOptions;
},
},

Webpack problem generating sourcemaps -- only generated when a particular plugin is disabled

I'm using my own custom plugin to strip some optional code from a build. This works well, but for some reason it seems to be blocking generation of source maps.
My best guess is that the fact that I'm modifying the index.js output file interferes with the ability to generate a map of for that file. If I comment out the plugin, my source maps come back.
Is there perhaps something I can do to change order of plugin execution that will fix this? Or perhaps a way to strip code from source file input streams (not from the files themselves) rather than from the generated output?
I've tried explicitly adding SourceMapDevToolPlugin to my plugins, but that didn't help.
Here's my webpack.config.cjs file:
const { Compilation, sources } = require('webpack');
const { resolve } = require('path');
module.exports = env => {
const esVersion = env?.esver === '5' ? 'es5' : 'es6';
const dir = env?.esver === '5' ? 'web5' : 'web';
const chromeVersion = env?.esver === '5' ? '23' : '51';
// noinspection JSUnresolvedVariable,JSUnresolvedFunction,JSUnresolvedFunction
return {
mode: env?.dev ? 'development' : 'production',
target: [esVersion, 'web'],
entry: {
index: './dist/index.js'
},
output: {
path: resolve(__dirname, 'dist/' + dir),
filename: `index.js`,
libraryTarget: 'umd',
library: 'tbTime'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: { presets: [['#babel/preset-env', { targets: { chrome: chromeVersion } }]] }
},
resolve: { fullySpecified: false }
}
]
},
resolve: {
mainFields: ['esm2015', 'es2015', 'module', 'main', 'browser']
},
externals: { 'by-request': 'by-request' },
devtool: 'source-map',
plugins: [
new class OutputMonitor {
// noinspection JSUnusedGlobalSymbols
apply(compiler) {
compiler.hooks.thisCompilation.tap('OutputMonitor', (compilation) => {
compilation.hooks.processAssets.tap(
{ name: 'OutputMonitor', stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE },
() => {
const file = compilation.getAsset('index.js');
let contents = file.source.source();
// Strip out dynamic import() so it doesn't generate warnings.
contents = contents.replace(/return import\(.*?\/\* webpackIgnore: true \*\/.*?tseuqer-yb.*?\.join\(''\)\)/s, 'return null');
// Strip out large and large-alt timezone definitions from this build.
contents = contents.replace(/\/\* trim-file-start \*\/.*?\/\* trim-file-end \*\//sg, 'null');
compilation.updateAsset('index.js', new sources.RawSource(contents));
}
);
});
}
}()
]
};
};
Full project source can be found here: https://github.com/kshetline/tubular_time/tree/development
I think using RawSource would disable the source map. The right one for devtool is supposed to be SourceMapSource so the idea looks like following:
const file = compilation.getAsset('index.js');
const {devtool} = compiler.options;
let contents = file.source.source();
const {map} = file.source.sourceAndMap();
// your replace work
// ...
compilation.updateAsset(
'index.js',
devtool
// for devtool we have to pass map file but this the original one
// it would be wrong since you have already changed the content
? new sources.SourceMapSource(contents, 'index.js', map)
: new sources.RawSource(contents)
);

Vue Cli 3 is not allowing me to process SVG's in Webpack

Vue Cli defaults to file-loader for SVG assets, but I want to use svg-sprite-loader (as well as a few others) instead.
I updated the vue.config.js file to do this and it still seems to use file-loader. Almost as though it's not picking up my config at all.
vue.config.js
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'svg-sprite-loader',
options: {
name: '[name]-[hash:7]',
prefixize: true
}
},
'svg-fill-loader',
'svgo-loader'
]
}
]
}
}
}
Is there anything wrong with my setup?
I'm still getting SVG files imported into my component as a URL string / path when it should be an object with properties.
Many thanks.
This took me a while to find a work around. Basically you need to stop file-loader matching on .svg. The best way I have found to do this is using chainWebpack and returning false from the test method on file-loader. I have included my working config.
module.exports = {
lintOnSave: false,
configureWebpack: {
module: {
rules: [
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'svg-inline-loader',
options: {
limit: 10000,
name: 'assets/img/[name].[hash:7].[ext]'
}
}
]
}
]
}
},
chainWebpack: config => {
config.module
.rule('svg')
.test(() => false)
.use('file-loader')
}
}
The Webpack docs for Vue CLI 3.0 beta got updated with an example on how to replace an existing Base Loader. For svg-sprite-loader this means that you'll have to add the following configuration to your vue.config.js:
chainWebpack: config => {
config.module
.rule('svg')
.use('file-loader')
.loader('svg-sprite-loader')
}
I'm using Vue CLI 3.0.3 and this config works for me 😉
const path = require('path');
const glob = require('glob');
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
module.exports = {
lintOnSave: false,
configureWebpack: {
plugins: [
new SpriteLoaderPlugin()
]
},
chainWebpack: config => {
config.module.rules.delete('svg');
config
.entry('app')
.clear()
.add(path.resolve(__dirname, './src/main.ts'))
config
.entry('sprite')
.add(...glob.sync(path.resolve(__dirname, `./src/assets/icons/*.svg`)));
config.module.rule('svg')
.test(/\.(svg)(\?.*)?$/)
.use('file-loader')
.loader('svg-sprite-loader')
.options({
extract: true,
spriteFilename: 'icons.svg'
})
}
};
Vue CLI docs for version 3.x in webpack section suggests to use something like this:
// vue.config.js
module.exports = {
chainWebpack: config => {
const svgRule = config.module.rule('svg')
// clear all existing loaders.
// if you don't do this, the loader below will be appended to
// existing loaders of the rule.
svgRule.uses.clear()
// add replacement loader(s)
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
}
Even vue-svg-loader configuration guide suggests same approach.
module.exports = {
chainWebpack: config => {
const svgRule = config.module.rule('svg')
svgRule.clear()
svgRule
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
}

Categories

Resources