quasar icon indicating copy to clipboard operation
quasar copied to clipboard

Quasar plugins don't work when inside npm packages

Open tanyongkuan opened this issue 3 years ago • 13 comments

What happened?

I am creating a app extension where the quasar notify method will be implemented as a utility file for all projects to utilise. I received the following error when I was using Vite.

image

I have also attempted to register the plugin via this but it isnt working as well.

conf.framework.plugins.push('Notify')

What did you expect to happen?

No error should be expected which I faced while using webpack

Reproduction URL

No link given as it is an app extension

How to reproduce?

It happens when running the quasar application with vite.

Flavour

Quasar CLI with Vite (@quasar/cli | @quasar/app-vite)

Areas

App Extension API

Platforms/Browsers

Firefox

Quasar info output

Global packages
  NPM - 8.5.5
  yarn - 1.22.18
  @quasar/cli - 1.3.2
  @quasar/icongenie - Not installed
  cordova - Not installed

Important local packages
  quasar - 2.7.6 -- Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
  @quasar/app-vite - 1.0.6 -- Quasar Framework App CLI with Vite
  @quasar/extras - 1.15.1 -- Quasar Framework fonts, icons and animations
  eslint-plugin-quasar - Not installed
  vue - 3.2.37 -- The progressive JavaScript framework for building modern web UI.
  vue-router - 4.1.3
  pinia - 2.0.17 -- Intuitive, type safe and flexible Store for Vue
  vuex - Not installed
  vite - 2.9.14 -- Native-ESM powered web dev build tool
  eslint - 8.21.0 -- An AST-based pattern checker for JavaScript.
  electron - Not installed
  electron-packager - Not installed
  electron-builder - Not installed
  register-service-worker - 1.7.2 -- Script for registering service worker, with hooks
  @capacitor/core - Not installed
  @capacitor/cli - Not installed
  @capacitor/android - Not installed
  @capacitor/ios - Not installed
Quasar App Extensions
  --My component library--

Relevant log output

TypeError: (intermediate value).create is not a function

Additional context

No response

tanyongkuan avatar Aug 02 '22 05:08 tanyongkuan

Hi @tanyongkuan! 👋

It looks like you provided an invalid or unsupported reproduction URL. Do not use any service other than Codepen, jsFiddle, StackBlitz, Codesandbox, and GitHub. Make sure the URL you provided is correct and reachable. You can test it by visiting it in a private tab, another device, etc. Please edit your original post above and provide a valid reproduction URL as explained.

Without a proper reproduction, your issue will have to get closed.

Thank you for your collaboration. 👏

github-actions[bot] avatar Aug 02 '22 05:08 github-actions[bot]

I have also attempted to register the plugin via this but it isnt working as well. conf.framework.plugins.push('Notify')

That's the way to go, but we can't be sure if you did it correctly or if there is something wrong.

Reproduction URL No link given as it is an app extension

I am pretty sure the app-ext code doesn't transfer via telepathy. So, we would need a GitHub repo to investigate the situation.

yusufkandemir avatar Aug 04 '22 07:08 yusufkandemir

Here's the repository.

https://github.com/tanyongkuan/notify-project

tanyongkuan avatar Aug 05 '22 01:08 tanyongkuan

I was able to reproduce the problem.

Repro steps

  1. Run these commands

    mkdir notify-app-ext-test
    cd notify-app-ext-test
    
    git clone [email protected]:tanyongkuan/notify-project.git app-ext
    
    yarn create quasar # App - Quasar v2 - Vite
    cd quasar-project
    yarn add --dev file:../app-ext # Install the app-ext locally
    
  2. Change script section of quasar-project/src/pages/IndexPage.vue to the following:

    <script setup>
    import { sendNotify } from 'quasar-app-extension-not-prj/src/js/utility';
    
    sendNotify('positive', 'test');
    </script>
    
  3. Start the project:

    yarn quasar dev
    

The problem

Quasar has an auto-loading/tree-shaking mechanism. The most important part of this problem is related to the JS transform part that is applied through the Quasar Vite Plugin. Normally, this:

import { Notify } from 'quasar'

gets turned into this:

import Notify from 'quasar/src/plugins/Notify'

But, that doesn't seem to be the case with app extensions, since they are not really processed as part of the app. So, quasar/src/plugins/Notify inside the app gets processed and installed, but the app-ext uses quasar, which points to the Quasar's usual pre-built bundles. So, Notify gets installed in one of them, but is not accessible in the other. So, we should add some kind of mechanism or configuration to transpile the app-ext, just like possible in app-webpack through the conf.build.transpileDependencies.push(/* ... */). This is also causing duplicates of Quasar in the build, increasing the bundle size.

Workaround

Manually transforming the imports. Instead of importing it the usual way, e.g.:

import { Notify } from 'quasar'

you can do this:

import Notify from 'quasar/src/plugins/Notify'

and similarly with other plugins/utils/components/etc., where needed as well.

yusufkandemir avatar Aug 05 '22 08:08 yusufkandemir

Thanks for the explanation!

tanyongkuan avatar Aug 08 '22 01:08 tanyongkuan

Just stumbled upon this while porting some "old" code from vuex/webpack into new vite/pinia quasar project. I don't know why this issue is closed when this is a bug(breaking change) that also does not match the documentation any more.

ivanjaros avatar Oct 08 '22 15:10 ivanjaros

It's still a problem on version 2.11.10

If not imported directly from the fully qualified path, under certain conditions that I don't know well, (I've tried in a fresh installation and everything works fine) it throws that error. And logging the Notify object shows that there's no create function at all, but there's a install on it's place alogn with setDefaults and registerType.

FlacorLopes avatar Apr 05 '23 05:04 FlacorLopes

@FlacorLopes I faced the same problem some days ago. I can't reproduce it right now anymore. Maybe I missed to install the plugin last time:

createApp(App)
  .use(Quasar, { 
    plugins: { Notify } 
  })
  .mount("#app");

agebhar1 avatar May 04 '23 18:05 agebhar1

Just wanna quickly highlight my solution to this problem: Add Notify into the plugins section of quasar.config.js did the trick for me

    framework: {
      config: {},

      // ...

      // Quasar plugins
      plugins: ['Notify'],
    },

apacha avatar Aug 30 '24 09:08 apacha

The issue should have stayed open for further investigation and fixes, so we are re-opening it.

The workaround provided earlier got changed and should be import Notify from 'quasar/src/plugins/notify/Notify' instead. If you are using TS in your library code, then you need to augment it, e.g.

declare module 'quasar/src/plugins/notify/Notify' {
    import { Notify } from 'quasar';
    export default Notify;
}

It might be helpful to mention that, when inside Vue render scope, $q.notify and similar should work. So, you can also give const $q = useQuasar() way a chance as another workaround.

yusufkandemir avatar Nov 28 '24 17:11 yusufkandemir

@yusufkandemir thanks for the help over on Discord.

Looking at the notify code, create is defined within the install method, so seems it needs to be installed. As such, I don't think I can use Notify at all within a plain NPM package any more.

Maybe an app extension has to be used after all?

DaleMckeown avatar Nov 28 '24 20:11 DaleMckeown

Any progress with this?

I tried researching myself a bit, but I was unable to find something solid as the origin of this problem I understand Yusuf's workaround, but it seems that it is not always working. Conditions when it does/doesn't are totally random to me at the moment.

Dtsiantaris avatar Jan 07 '25 08:01 Dtsiantaris

Hello! I followed the workaround that @yusufkandemir suggested, by moving my notification helper in a Composable (so that we stay in a Vue render scope). It worked well in my case. Here's my snippet :

// useNotificationService.ts

export function useNotificationService() {
   const $q = useQuasar()
   
   const notify = (...) => {
       $q.notify({ ... })
   }

  return { notify }
}

And the usage in some component :

<script setup>
import { useNotificationService } from 'useNotificationService.ts'
// ...
const notificationService = useNotificationService()
notificationService.notify(...)
</script>

furtivesock avatar Oct 07 '25 15:10 furtivesock