У меня тоже она возникла. Причём интересно, что при компиляции на локальных компьютерах (Ubuntu) всё в порядке, а на одном серверном окружении (CentOS Linux 7) с теми же условиями компиляции — ошибка. (Там и там — последние NodeJS.)
Она оказалась в node_modules/vue-template-compiler/build.js и в node_modules/vue-template-compiler/browser.js действительно, в функции repeat$1. При втором параметре, меньшем 0 она даёт эту ошибку. В исходном пакете последней версии 2.6.6 — не исправлена, 2.5.17 — тоже. Чтобы не возникала, надо функцию записать так (например):
function repeat$1 (str, n) {
var result = '';
while (true) { // eslint-disable-line
// if (n & 1) { result += str; }
// n >>>= 1;
// if (n <= 0) { break }
if(str.length >280 || (n && (result += str), (n >>>= 1) <= 0)) break;
str += str;
}
return result
}
Или патчил сжатую функцию так:
function Ra(e,t){for(var n="";;){if(e.length >280 || (t && (n += e), (t >>>= 1) <= 0))break;e+=e}return n}
В процессе работы выполнение кода repeat$1(‘^’,-1) приводило к ошибке, в пропатченном варианте — нет.
In our teams we have been using single SPA for a while and love it. The different teams use Angular, React and Vue applications. They all work really well together. However, recently we tried to convert one of the Vue applications from version 2 to version 3 with Typescript and that’s when we encountered problems.
To Replicate
I have setup an example repository with instructions to replicate here: https://github.com/smilyanp/mf-setup
The error
The error we see is this:
In more detail
I don’t claim that we’re doing everything correctly, but this is what has worked previously and now it doesn’t, thus me raising the issue.
The setup is simple, in the host application we load:
{
"imports": {
"@mf-setup/react-app": "/node_modules/@mf-setup/react-app/dist/react-app.umd.js",
"@mf-setup/vue-app": "/node_modules/@mf-setup/vue-app/dist/index.umd.js"
}
}
And we register the application as:
singleSpa.registerApplication(
'react-app',
() => load('@mf-setup/react-app'),
showWhenPrefix(['/user-management', '/user/profile']),
{ environment, eventBus, features },
);
singleSpa.registerApplication(
'vue-app',
() => load('@mf-setup/vue-app'),
showWhenPrefix(['/user/profile']),
{ environment, eventBus, features },
);
That all works ok and there is no issue loading the source for each application under the respective route.
This is where things become a bit more difficult and potentially we are doing it incorrectly, but again, it has worked previously.
The React application loads the contents of the Vue application for a given route
In our case, the React application has a lot of different functionality and we want it to load the contents of the Vue application which should be independent. To do so, the React application provides a placeholder element on it’s route, a <div id="vue-app"></div>
with an ID that the Vue application can bind to:
<Router>
<Switch>
<Route path="/user-management" component={() => {
return (
<div>
<h2>React App Content:</h2>
<div>Some content provided by the react app</div>
</div>
)
}} />
<Route exact path="/user/profile" component={() => {
return (
<div>
<h2>Vue App Content:</h2>
<div id="vue-app"></div>
</div>)
}} />
</Switch>
</Router>
When the user goes to /user/profile
route the @mf-setup/vue-app
source code correctly loads on the page (the console.logs show that and also the network tab).
Inside of the Vue application we abstract the mount to wait until the HTML element is available in the DOM thus:
vueLifecycles = singleSpaVue({
createApp,
appOptions: {
render () {
return h(App, {
name: this.name,
// @ts-expect-error single-spa docs claim these properties exist...
mountParcel: this.mountParcel,
// @ts-expect-error single-spa docs claim these properties exist...
singleSpa: this.singleSpa,
});
},
el: `#vue-app`,
},
replaceMode: true,
});
mount = async (props) => {
waitForElement('vue-app', () => vueLifecycles.mount(props));
};
export { mount, unmount, bootstrap };
This has worked previously without issues, and also we can see that the <App />
component is mounted as well, because in the created()
lifecycle hook there is a console.log that appears in the console.
However, the contents of that component are never rendered on the page and instead we see the error shown above.
Any help on this would greatly be appreciated.
In software development, things are not as smooth as they may seem to the user. There are always errors and bugs that developers must deal with behind the scenes. As you might imagine, debugging and error tracing can be time-consuming, and the tools you use can make a huge difference in productivity.
If you’re using Vue.js, you’ve surely encountered various types of errors, and there’s usually more than one way to handle them. In this tutorial, we’ll review some best practices and demonstrate how to handle errors, set up a debugger, and trace errors efficiently in Vue.js.
We’ll use Vue CLI to set up our demo project, a to-do app that displays a list of items from the Placeholder API.
The full code for this project is available on GitHub.
What is error handling?
Error handling refers to the process of tracing, handling, and resolving application errors without negatively affecting the user experience. It aims to accomplish three objectives:
- Prevent the application from breaking unexpectedly in production when there’s an unhandled exception
- Discover what happened when an error is logged
- Improve the user experience (e.g., by displaying messages when bugs are discovered and fixed)
What is debugging?
Debugging is the process of identifying and removing errors and resolving bugs in software. It involves analyzing a problem, identifying its origin, determining the cause, and charting a course to resolve it as efficiently as possible.
Debugging in Vue.js
Vue.js provides a debugger that helps you handle errors and quickly address bugs in your application. VueJs Debugger is well-integrated with VSCode and both Chrome and Firefox.
First, download and install the Vue Debugger extension for Chrome or Firefox. You can read more on how to configure it in the Vue.js docs.
Once you’ve installed the debugger, go to VSCode Activity Bar and click the debugging icon. You’ll see a gear/settings icon. Click it and select your preferred browser.
Next, open the launch.json
file and paste in the corresponding configuration based on the browser you selected.
Once the setup is complete, tracing errors is as easy as setting up several breakpoints in your application and running the debugger you just installed.
What is tracing?
Tracing is the process of searching for the origin of an error and identifying the cause in a stack trace.
As you might’ve guessed, Vue Debugger also makes tracing a lot easier.
Setting up a breakpoint
Before you can achieve effective tracing, you need to learn how to set up a breakpoint.
Double-click on the line number in your VSCode to add a breakpoint. Then, run npm run serve
to serve your project. Go to the debug view in your editor and select your preferred browser configuration. Press 5 or click the green play button. At this point, your breakpoints should hit when the code executes.
If you look at the debug view, you can spot some useful data for debugging your application.
Handling errors in Vue.js
Handling errors in a Vue.js application can be complicated. The best approach is to break it into steps.
In any application I develop, I always formulate a plan for handling errors, usually by creating a generic ErrorService
class and including functions to handle and process the errors coming in according to their type.
Types of errors
There are four main types of errors you’re likely to encounter in your Vue.js app:
- Syntax errors occur when you use the wrong syntax
- Runtime errors are caused by illegal operations during execution
- Logical errors are difficult to identify because they result from mistakes in the program logic
- HTTP errors are common when you’re working with APIs
Now let’s zoom in on some specific examples of error handling and debugging activities you can perform with Vue Debugger.
Create an error service in Vue.js
The ErrorService
class will handle all your errors and decide how to process them.
import Swal from "sweetalert2"; import "sweetalert2/dist/sweetalert2.min.css"; export default class ErrorService { constructor() { // this.initHandler(); } static onError(error) { const response = error.response; if (response && response.status >= 400 && response.status < 405) { // You can handle this differently ErrorService.sentryLogEngine(error); return false; } // Send Error to Log Engine e.g LogRocket ErrorService.logRocketLogEngine(error); } static onWarn(error) { // Send Error to Log Engine e.g LogRocket this.logRocketLogEngine(error); } static onInfo(error) { // You can handle this differently this.sentryLogEngine(error); } static onDebug(error) { const response = error.response; if (response && response.status >= 400 && response.status < 405) { // You can handle this differently this.sentryLogEngine(error); return false; } // Send Error to Log Engine e.g LogRocket this.logRocketLogEngine(error); } static initHandler() { const scope = this; window.onerror = (message, url, lineNo, columnNo, error) => { console.log(error, "test"); if (error) { scope.onError(error); console.log(message, url, lineNo, columnNo, error); } }; } static displayErrorAlert(message) { Swal.fire({ title: "Error!", text: message, icon: "error", }); } static logRocketLogEngine(error) { // Implement LogRocket Engine here console.log(error, "LogRocket"); } static sentryLogEngine(error) { // Implement Sentry Engine here console.log(error, "Sentry"); } }
Catch all possible Vue errors
Vue.js offers an error handler to catch all possible Vue errors. You can do this inside the main.js
file.
import Vue from "vue"; import App from "./App.vue"; import { ErrorService } from "./Services/ErrorService"; import store from "./store"; Vue.config.productionTip = false; // Handle all Vue errors Vue.config.errorHandler = (error) => ErrorService.onError(error); new Vue({ store, render: (h) => h(App), }).$mount("#app");
ErrorService
in Vuex
Using the ErrorService
class in Vuex is a great way to handle and process HTTP errors from Axios. You can also store the errors in Vuex State so they can be displayed to the user gracefully.
import Vue from "vue"; import Vuex from "vuex"; import { ErrorService } from "./Services/ErrorService"; import axios from "axios"; Vue.use(Vuex); const store = new Vuex.Store({ state: { todos: [], errors: [], users: [], }, actions: { async getTodos({ commit }) { try { const response = await axios.get( `https://jsonplaceholder.typicode.com/todos` ); const { data } = response; commit("STORE_TODOS", data); } catch (error) { // Handling HTTPs Errors commit("STORE_ERRORS", error); } }, async getUsers({ commit }) { try { const response = await axios.get( `https://jsonplaceholder.typicode.com/users` ); const { data } = response; commit("STORE_USERS", data); } catch (error) { // Handling HTTPs Errors commit("STORE_ERRORS", error); } }, }, mutations: { STORE_TODOS: (state, data) => { state.todos = data; }, STORE_ERRORS: (state, error) => { // Call Error Service here ErrorService.onError(error); ErrorService.initHandler(); // Store error to state(optional) if (error.response) { state.errors = error.response; } }, STORE_USERS: (state, data) => { state.users = data; }, }, getters: { getTodo: (state) => (id) => { return state.todos.find((todo) => todo.id == id); }, getUser: (state) => (id) => { return state.users.find((user) => user.id == id); }, }, // strict: true }); export default store;
Displaying errors in a component
Since the errors are saved in the Vuex State, which enables us to leverage the reactivity of Vue, we can display them on the error component like so:
<script> import { mapGetters } from "vuex"; import ErrorService from "../Services/ErrorService"; export default { name: "HelloWorld", props: { todo: Object, }, computed: { ...mapGetters(["getUser"]), }, methods: { getUserName(id) { const user = this.getUser(id); if (user) return user.username; }, // Handling Errors in component methodThrowsException() { try { // Do unexpected job } catch (error) { ErrorService.onError(error); } }, }, }; </script>
Displaying errors with plugins in Vue.js
You can display these errors to the user in different ways. We’ll use the vue-sweetalert2 plugin to display our errors.
<script> import { mapGetters } from "vuex"; import ErrorService from "../Services/ErrorService"; export default { name: "HelloWorld", props: { todo: Object, }, computed: { ...mapGetters(["getUser"]), }, methods: { getUserName(id) { const user = this.getUser(id); if (user) return user.username; }, // Display Error with SweetAlert (when Name is Click) displayAlert() { ErrorService.displayErrorAlert("Testing message"); }, }, }; </script>
Conclusion
The ability to handle errors and resolve bugs in your application efficiently is crucial. If you want to maximize your productivity, choosing the right tools and methods for debugging your Vue.js app can make a huge difference.
Hopefully, this walkthrough gave you a solid, foundational understanding of error management, debugging, and tracing in VueJS.
Experience your Vue apps exactly how a user does
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — Start monitoring for free.
В этой статье я хотел бы описать встроенные методы обработки ошибок существующие во Vue.js. Очевидно, что я не опишу каждый возможный сценарий, но я надеюсь, что эта статья поможет познакомиться с работой с ошибками во Vue.js!
Ошибки!
Чтобы протестировать различные методы обработки ошибок, я решил использовать три разных типа ошибок. Первый просто ссылка на переменную, которой не существует:
<div id="app" v-cloak> Hello, {{name}} </div>
Этот пример не будет отображать ошибку для пользователя, он должен выводить предупреждение [Vue warn] в консоль.
Вы можете просмотреть этот пример здесь:
Для второго примера я попытался связать переменную с вычисляемым свойством, которая выводит ошибку:
<div id="app" v-cloak> Hello, {{name2}} </div> <script> const app = new Vue({ el:'#app', computed:{ name2() { return x; } } }) </script>
Этот код так же выдает [Vue warn] и обычную ошибку в консоли но при этом ничего не показывает пользователю в окне браузера.
Вот код для него.
Для третьей ошибки я использовал метод, который выдает ошибку при выполнении.
<div id="app" v-cloak> <button @click="doIt">Do It</button> </div> <script> const app = new Vue({ el:'#app', methods:{ doIt() { return x; } } }) </script>
Как и предыдущая, эта ошибка будет выводится дважды в консоли, одно предупреждение и одна ошибка. В отличие от прошлого раза, ошибка появляется только тогда, когда вы нажмете на кнопку.
И вот код для него:
Хорошо, прежде чем мы продолжим, я просто хочу прояснить, что эта выборка не репрезентативно для каждого типа ошибок, которые можно создать, это всего лишь базовый показатель из нескольких вариантов, который, я думаю, достаточно распространены в приложениях Vue.js.
Итак, как вы обрабатываете ошибки в приложениях Vue? Я должен сказать, что был немного удивлен, что в главном Vue Guide не было четко определенного раздела по обработке ошибок.
Да, есть общее описание в руководстве, но текст достаточно короткий, и весь может поместиться в одну цитату:
Если во время рендеринга компонента возникает ошибка выполнения, она будет передана в глобальную конфигурационную функцию Vue.config.errorHandler(если она была задействована). Возможно, было бы неплохо использовать этот хук вместе с сервисом отслеживания ошибок, таким как Sentry, который обеспечивает официальную интеграцию для Vue.
На мой взгляд, эта тема должна быть описана более подробно в документации. В общем, обработка ошибок в Vue сводится к следующим методам:
- errorHandler
- warnHandler
- renderError
- errorCaptured
- window.onerror (не Vue-специфическая техника)
Первый метод обработки ошибок: errorHandler
Первый метод, который мы рассмотрим, это errorHandler. Как вы можете догадаться, это общий обработчик ошибок для приложений Vue.js. Его использование выглядит так:
Vue.config.errorHandler = function(err, vm, info) { }
В приведенном выше объявлении переменная err – это фактический объект ошибки, info – это строка ошибки, специфичная для Vue, а vm – фактическое приложение Vue. Помните, что одновременно на одной веб-странице может работать несколько приложений Vue. Этот обработчик ошибок будет применяться ко всем из них. Рассмотрим этот простой пример:
Vue.config.errorHandler = function(err, vm, info) { console.log(`Error: ${err.toString()}nInfo: ${info}`); }
Для первого примера кода эта обработка ошибки ничего не делает. Если вы помните, оно выдает предупреждение, а не ошибку.
Для второго примера кода, она обработает ошибку и выдаст сообщение:
Error: ReferenceError: x is not defined Info: render
Наконец, для третьего примера она выдаст такой сообщение:
Error: ReferenceError: x is not defined Info: v-on handler
Теперь давайте проверим следующий метод.
Второй метод обработки ошибок: warnHandler
warnHandler Vue предупреждения. Обратите внимание, что этот обработчик игнорируется во время режима продакт. Обработчик метода также немного отличается:
Vue.config.warnHandler = function(msg, vm, trace) { }
Переменные msg, и vm самоочевидны, а trace содержит дерево компонентов. Рассмотрим этот пример:
Vue.config.warnHandler = function(msg, vm, trace) { console.log(`Warn: ${msg}nTrace: ${trace}`); }
Первый пример кода теперь обрабатывается и выдает предупреждения:
Warn: Property or method 'name' is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties. Trace: (found in <Root>)
Второй и третий примеры не меняются. Вы можете просмотреть работу примером ниже:
Третий метод обработки ошибок: renderError
Третий метод, который я продемонстрирую, это renderError. В отличие от предыдущих двух, этот метод используется только внутри компонентов, а не глобально. Также, как warnHandler, он отключен в режиме продакт.
Чтобы его использовать, нужно описать его в компоненте или приложение. Пример использования:
const app = new Vue({ el:'#app', renderError (h, err) { return h('pre', { style: { color: 'red' }}, err.stack) } })
Если он использовать в первом примере с ошибкой, он ничего не делает, так как первый выдает предупреждение, а не ошибку. Если вы задействуете его во втором, c вычисляемым свойством то будет вывод ошибки на экрана браузера. Вы можете увидеть это в коде ниже.
Честно говоря, я не уверен, для каких целей я бы использовал этот метод. На мой взгляд консоль более подходящее место для вывода ошибок, но если ваша команда QA или другие тестировщики не знакомы с консолью браузера, этот метод может помочь вывести сообщение об ошибке на экране.
Четвертый метод обработки ошибок: errorCaptured
Финальный (специфичной для Vue) метод errorCaptured. В документации о нем сказано:
Вызывается, когда фиксируется ошибка любого потомка компонента. Хук получает три аргумента: ошибку, экземпляр компонента, который вызвал ошибку, и строку, содержащую информацию о том, где была зафиксирована ошибка. Хук может вернуть false, чтобы предотвратить дальнейшее распространение ошибки.
Основываясь на моих исследованиях (я определенно шокирован этим), этот обработчик ошибок должен использоваться только «родительским» компонентом, обрабатывающим ошибку «дочернего» компонента. Насколько я знаю, его нельзя использовать в основном экземпляре Vue, только в компоненте с дочерними элементами.
Чтобы проверить этот метод, я создал родительский / дочерний набор компонентов, например:
Vue.component('cat', { template:` <div><h1>Cat: </h1> <slot></slot> </div>`, props:{ name:{ required:true, type:String } }, errorCaptured(err,vm,info) { console.log(`cat EC: ${err.toString()}ninfo: ${info}`); return false; } }); Vue.component('kitten', { template:'<div><h1>Kitten: </h1></div>', props:{ name:{ required:true, type:String } } });
Обратите внимание, что в компоненте kitten есть ошибка. Теперь, если я попытаюсь использовать:
<div id="app" v-cloak> <cat name="my cat"> <kitten></kitten> </cat> </div>
Я получу сообщение от обработчика:
cat EC: TypeError: dontexist is not a function info: render
Вы можете просмотреть это в коде ниже.
Так что да … интересный метод. Я предполагаю, что он будет в основном использоваться людьми, создающими библиотеки компонентов с отношениями типа родительский / дочерний. Это скорее метод «разработчика библиотеки», чем метод «обычного разработчика». Но опять же – это только мое первоначальное впечатление от этого метода.
Единый метод, чтобы управлять ими всеми: window.onerror
Последний (и самый мощный) вариант – использование window.onerror, глобальный обработчик ошибок для всего, что может пойти не так с вашим JavaScript. Обработчик имеет форму:
window.onerror = function(message, source, line, column, error) { }
Вероятно, единственное,о чем вы не можете догадаться, это что такое переменная source. В ней содержится URL скрипта. Здесь все становится интереснее. Если вы определите этот метод и не используете Vue.config.errorHandler, то он не будет работать. Vue ожидает, что вы определите errorHandler а, если вы этого не сделаете, не распространит ошибку за пределы себя.
Вот пример использование этого метода. Я закомментировал ошибку в errorHandler, но если вы удалите комментарий, вы увидите, что глобальный обработчик ошибок не запускается. Единственное, что вы можете увидеть – запуск глобального обработчика, при нажатие на вторую кнопку.
Заключение
Я надеюсь, что эта статья была для вас полезна. Мне бы очень хотелось услышать, как люди используют эти методы в своих приложениях!
Перевод статьи: Handling Errors in Vue.js
Была ли вам полезна эта статья?
In this article, you are going to learn about how to fix Uncaught ReferenceError: Vue is not defined.
“Uncaught ReferenceError: Vue is not defined” is a common problem and if you are an absolute beginner you will face this problem once in your programming career. This error may occur for a few reasons. I will explain my experience while I was facing this problem and how I solved it and later on I will show a few other reasons for this problem and the solution for it. First see the error below:
I was facing this error while working with Vue and first I have no idea why this was happening. But later on, I have figured out that I was linking my files in the wrong order. I was linking my app.js file first and then the Vue CDN file and for this reason, I was getting that particular error. See the wrong code in the below example:
<script src="app.js"></script>
<script src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js>"></script>
This is the wrong order. You have to link the CDN file first and your own created file and this is the convention of linking JavaScript files into HTML. When I follow the convention the error has vanished. See the correct code in the below example:
<script src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js>"></script>
<script src="app.js"></script>
If you have faced this error, you should check the HTML file. In there if you link JavaScript file in the wrong order then write it in the right order and this will fix the problem.
Now, if you maintain the order and still have faced error then there will be a different cause for it. You may create a type error while importing Vue in your project. See the below code example :
import Vue from 'Vue'
If you write this code while importing Vue, you will simply get “Uncaught ReferenceError: Vue is not defined” this error. Because you have spelled in the correct form but both’s first latter in UpperCase. Which is creating the case-sensitive issue. See the correct code in the below example:
import Vue from 'vue'
This problem has occurred for some silly mistakes. You need to be careful and focus while working with Vue and by doing this you may avoid this kind of error.
This guide is part of the “Common Vue Errors” series. It’s focused entirely on providing quick and easy solutions for Vue-related problems.
Deven
Deven is an Entrepreneur, and Full-stack developer, Constantly learning and experiencing new things. He currently runs CodeSource.io and Dunebook.com