Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't Load Extension NODE_MODULE boot files If not rendered to main app #4804

Closed
emahuni opened this issue Aug 3, 2019 · 4 comments
Closed

Comments

@emahuni
Copy link

emahuni commented Aug 3, 2019

Describe the bug
I don't know whether to call this a bug or a feature, but the thing is it seems like extensions are being made with the assumption that I would expose everything to the hosting app using the templates folder, ie: api.render(...). I have noticed that this is actually undesirable most of the time since it will blot the main app with non problem-domain-specific code. It's like putting all node_modules code into your app src folder on installation. I know there is the desire to customize extensions and this is fine, but most of the time extensions want to add that needed feature being without blotting the actual app they are extending and live in the node_modules dir.

You may say yah you could do that no problem, but here is the problem. You can't refer to boot files in an extension if that extension doesn't expose them in the main app for example.

To Reproduce

  1. create an extension and that boot file at that path:
// extension/src/boot/boot-file.js
   export default async ({ app, router, Vue, store }) => {
      console.info(`Weeee I am a nice boot file!...`);
   }
  1. Now, push the boot file into Quasar conf using the extension API in extension index.js file
// extension/index.js
    api.extendQuasarConf((conf) => {
       conf.boot.push('extension/src/boot/boot-file.js');
    }
  1. install the extension into a Quasar app and run

  2. It will throw:

 ERROR  Failed to compile with 1 errors                                                                                                                                                            
This dependency was not found:

* boot/extension/src/boot/boot-file.js in ./.quasar/client-entry.js

it won't be able to load that boot file in the main app. I went thru the logic and noticed that it expects all boot files to be in app/src/boot. Meaning that extension boots are not honoured as long as they are outside of the main app folders eg: node_modules/extension/src/boot/boot-file.js.

Codepen/jsFiddle/Codesandbox (required)
I cant, last time this didnt work for extensions

Expected behavior
I expect this be able to honour node_modules paths as well such that if I refer to a file in node_modules it should just pick it up. The Quasar Config logic should try to get the file from boots folder as usual, if it can't find it, it should then try to do a regular import using regular node module import ie: from the node_modules before throwing an error, and 'extension/src/boot/boot-file.js' should work fine.

Platform (please complete the following information):
Quasar 1.0.5

Additional context
My solution to this is as follows. I created one boot file node_modules/extension/src/templates/src/boot/boot-proxy.js and rendered that to the main app/src/boot dir as app/src/boot/boot-proxy.js, and did that config boot push above of that file. In that boot proxy file i then properly imported the boot files I need to boot up from node_modules and invoked each one as Quasar does it.

import boot from '@emanimation/quasar-app-extension-em-qui/src/boot/boot.boot.js';
import utils from '@emanimation/quasar-app-extension-em-qui/src/boot/utils.boot.js';
import stores from '@emanimation/quasar-app-extension-em-qui/src/boot/stores.boot.js';
import components from '@emanimation/quasar-app-extension-em-qui/src/boot/components.boot.js';
import globalMixin from '@emanimation/quasar-app-extension-em-qui/src/boot/global-mixin.boot.js';
import auth from '@emanimation/quasar-app-extension-em-qui/src/boot/auth.boot.js';

/**
 * this is a workaround issue where boot files cannot be injected from outside the quasar app
 * @param app
 * @param router
 * @param Vue
 * @param store
 * @returns {Promise<void>}
 */
export default async ({ app, router, Vue, store }) => {
  console.info(`Booting up em-qui boot scripts...`);

  const bootFiles = [
    boot,
    utils,
    stores,
    components,
    globalMixin,
    auth,
  ];

  for (let i = 0; i < bootFiles.length; i++) {
    try {
      await bootFiles[i]({
        app,
        router,
        store,
        Vue,
        ssrContext: null,
      });
    } catch (err) {
      if (err && err.url) {
        window.location.href = err.url;
        return;
      }

      console.error('[Quasar] boot error:', err);
      return;
    }
  }
}

This works, but it could've been better if this just those few lines at the top without the import ... from.

@hawkeye64
Copy link
Member

hawkeye64 commented Aug 4, 2019

I have writted a LOT of App Extensions and personally I don't use the templates folder. This is a choice. You fully understand how it can be used, but open your mind to other possibilities.

For my AEs, I create this structure:
image
Inside boot folder contains the boot file with the following code:

import MyComponent from 'quasar-app-extension-my-component/src/component/MyComponent'

export default ({ Vue, ssrContext }) => {
  Vue.component('my-component', QMyComponent(ssrContext))
}

In index.js, the boot file is injected into the build (among other things) like this:

const extendConf = function (conf) {
  // make sure my-component boot file is registered
  conf.boot.push('~quasar-app-extension-my-component/src/boot/my-component.js')
  console.log(` App Extension (my-component) Info: 'Adding my-component boot reference to your quasar.conf.js'`)

  // make sure boot & component files transpile
  conf.build.transpileDependencies.push(/quasar-app-extension-my-component[\\/]src/)

  // make sure qplaceholder css goes through webpack to avoid ssr issues
  conf.css.push('~quasar-app-extension-my-component/src/component/my-component.styl')
  console.log(` App Extension (my-component) Info: 'Adding my-component.styl css reference to your quasar.conf.js'`)
}

module.exports = function (api) {
  // quasar compatibility check
  api.compatibleWith('@quasar/app', '^1.0.0')

  // extend quasar.conf
  api.extendQuasarConf(extendConf)
}

Now, don't get me wrong. There is a need for the render api and templates. But, it really depends on what you are doing with your app extension.

If you need more information and/or demos, you can check out any of the App Extension I have written:

UI AEs

https://github.com/quasarframework/app-extension-qcalendar
https://github.com/quasarframework/app-extension-qmarkdown
https://github.com/quasarframework/app-extension-qmediaplayer
https://github.com/quasarframework/app-extension-qflashcard
https://github.com/quasarframework/app-extension-qpdfviewer
https://github.com/quasarframework/app-extension-qactivity
https://github.com/quasarframework/app-extension-qiconpicker
https://github.com/quasarframework/app-extension-qscroller
https://github.com/quasarframework/app-extension-qoverlay

Runner AEs

https://github.com/quasarframework/app-extension-qenv
https://github.com/quasarframework/app-extension-dotenv

@emahuni
Copy link
Author

emahuni commented Aug 5, 2019

Thanks you so much for the info. If notice, I didn't intend to use the templates folder at all, and getting my extension's boot files to be included in the main Quasar app was the issue. I only used that boot proxy to mitigate the problem I was facing. I will use your recommendation, but I think what I proposed still has a bit of merit since it's intuitive to developers.

@emahuni
Copy link
Author

emahuni commented Aug 5, 2019

Let me reword the title of this issue to properly horn in on the issue

@emahuni emahuni changed the title Can't Load Extension boot files If not rendered to main app Can't Load Extension NODE_MODULE boot files If not rendered to main app Aug 5, 2019
@rstoenescu
Copy link
Member

Hi,

If you want to register boot files in quasar.conf.js from node_modules, then put ~ (ampersand character) in front of your package name as indicated by @hawkeye64 earlier.
Same goes for registering css in quasar.conf.js.

Please reopen if I misunderstood something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants