Nuxt.js - external component does not work inside another component after npm generate - vue.js

On the page I use my component that I import locally.
Inside that component I use an external one (vue-carousel) but since it's client only, I've built a plugin that imports the vue-carousel and registers its components globally.
It works on npm run dev but if I run npm run generate it stops working and in the inspector I see the tags instead of the component itself. I use a local IIS setup.
Demo repo: https://github.com/MrZordex/inner-component-problem
Any ideas how that could happen?

Change your nuxt.config.js file:
plugins: [
{src: '#/plugins/vue-carousel.client.js', mode: 'client'}
// {src: '#/plugins/vue-carousel.client.js', ssr: false} // or
]
Some plugins might work only in the browser because they lack SSR support. In these situations you can use the mode: client option in plugins to add the plugin only on the client-side.
Note: Since Nuxt.js 2.4, mode has been introduced as option of plugins to specify plugin type, possible value are: client or server. ssr: false will be adapted to mode: 'client' and deprecated in next major release.

Related

Parsehub "This Stencil app is disabled for this browser."

I need to scrape some data from transfermarkt.com using parsehub, but when i try to load the website with parse hub I'm only met with:
This Stencil app is disabled for this browser.
Developers:
ES5 builds are disabled during development to take advantage of 2x faster build times.
Please see the example below or our config docs if you would like to develop on a browser that does not fully support ES2017 and custom elements.
Note that as of Stencil v2, ES5 builds and polyfills are disabled during production builds. You can enable these in your stencil.config.ts file.
When testing browsers it is recommended to always test in production mode, and ES5 builds should always be enabled during production builds.
This is only an experiment and if it slows down app development then we will revert this and enable ES5 builds during dev.
Enabling ES5 builds during development:
npm run dev --es5
For stencil-component-starter, use:
npm start --es5
Enabling full production builds during development:
npm run dev --prod
For stencil-component-starter, use:
npm start --prod
Current Browser's Support:
ES Module Imports: false
ES Dynamic Imports: false
Custom Elements: false
Shadow DOM: false
fetch: true
CSS Variables: true
Current Browser:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0
I tried following the steps to enable ES5, but it does not work.
If i go to the website on the standard firefox browser it works like normal, but not in parsehub
That message indicates that the browser does not support JS modules. Looking at parsehub's FAQ they are using Firefox v54 which was released in 2017 and does not support JS modules.
Starting with version 2 Stencil has changed legacy browser support to be opt-in.
If you have access to the source code you can add legacy browser support using the following config:
export const config: Config = {
buildEs5: 'prod',
extras: {
cssVarsShim: true,
__deprecated__dynamicImportShim: true,
shadowDomShim: true,
safari10: true,
scriptDataOpts: true,
appendChildSlotFix: false,
cloneNodeFix: false,
slotChildNodesFix: true,
}
};
The only other options are:
ask the site to add those config changes and publish a new version
use a different scraper with a more recent version

Change Nuxt.js SPA mode to Universal mode

I've chosen SPA mode when I first created the project, but after a while I want to change it to Universal mode. Is it possible to change it from nuxt.config.js?
For the ones who receive the deprecation warning now instead of using mode: "universal"
You have to do the next in your nuxt.config.js
export default {
ssr: true,
}
Yes you can easily change it on your nuxt.config.js file by change mode:'spa' to mode:'universal'. Here is the docs.
Also remember after you do this if your server is running you need to stop and re-run it again.

Bundling a plugin with Rollup but having duplicate Vue.js package imported in the client app's bundle (Nuxt)

Dear Stack Overflow / Vue.js / Rollup community
This could be a noob question for the master plugin developers working with Vue and Rollup. I will write the question very explicitly hoping that it could help other noobs like me in the future.
I have simple plugin that helps with form validation. One of the components in this plugin imports Vue in order to programatically create a component and append to DOM on mount like below:
import Vue from 'vue'
import Notification from './Notification.vue' /* a very simple Vue component */
...
mounted() {
const NotificationClass = Vue.extend(Notification)
const notificationInstance = new NotificationClass({ propsData: { name: 'ABC' } })
notificationInstance.$mount('#something')
}
This works as expected, and this plugin is bundled using Rollup with a config like this:
import vue from 'rollup-plugin-vue'
import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: 'src/index.js',
output: {
name: 'forms',
globals: {
vue: 'Vue'
}
},
plugins: [
vue(),
babel(),
resolve(),
commonjs(),
terser()
],
external: ['vue']
}
As you can see, Vue.js is getting externalised in this bundle. The aim (and the assumption) is that the client app that imports this plugin will be running on Vue, therefore there's no need to bundle it here (assumption).
The very simple src/index.js that the bundler uses is below:
import Form from './Form.vue'
export default {
install(Vue, _) {
Vue.component('bs-form', Form)
}
}
Rollup creates 2 files (one esm and one umd) and references them in in the plugins package.json file like below:
"name": "bs-forms",
"main": "./dist/umd.js",
"module": "./dist/esm.js",
"files": [
"dist/*"
],
"scripts": {
"build": "npm run build:umd & npm run build:es",
"build:es": "rollup --config rollup.config.js --format es --file dist/esm.js",
"build:umd": "rollup --config rollup.config.js --format umd --file dist/umd.js"
}
Everything works as expected up to this point and the bundles are generated nicely.
The client app (Nuxt SSR) imports this plugin (using npm-link since it's in development) with a very simple import in a plugin file:
/* main.js*/
import Vue from 'vue'
import bsForms from 'bs-forms'
Vue.use(bsForms)
This plugin file (main.js) is added to nuxt.config.js as a plugin:
// Nuxt Plugins
...
plugins: [{src: '~/plugins/main'}]
...
Everything still works as expected but here comes the problem:
Since the clients is a Nuxt app, the Vue is imported by default of course but the externalised Vue module (by the forms plugin) is also imported in the client. Therefore there is a duplication of this package in the client bundle.
I guess the client app can configure its webpack config in order to remove this duplicated module. Perhaps by using something like a Dedupe plugin or something? Can someone suggests how to best handle situation like these?
But what I really want to learn, is the best practice of bundling the plugin at the first place, so that the client doesn't have to change anything in its config and simply imports this plugin and move on.
I know that importing the Vue.js in the plugin may not be a great thing to do at the first place. But there could be other reasons for an import like this as well, for example imagine that the plugin could be written in Typescript and Vue.js / Typescript is written by using Vue.extend statements (see below) which also imports Vue (in order to enable type interface):
import Vue from 'vue'
const Component = Vue.extend({
// type inference enabled
})
So here's the long question. Please masters of Rollup, help me and the community out by suggesting best practice approaches (or your approaches) to handle situations like these.
Thank you!!!!
I had the same problem and I found this answer of #vatson very helpful
Your problem is the combination of "npm link", the nature of nodejs module loading and the vue intolerance to multiple instances from different places.
Short introduction how import in nodejs works. If your script has some kind of library import, then nodejs initially looks in the local node_modules folder, if local node_modules doesn't contain required dependency then nodejs goes to the folder above to find node_modules and your imported dependency there.
You do not need to publish your package on NPM. It is enough if you generate your package locally using npm pack and then install it in your other project npm install /absolute_path_to_your_local_package/your_package_name.tgz. If you update something in your package, you can reinstall it in your other project and everything should work.
Here is the source about the difference between npm pack and npm link https://stackoverflow.com/a/50689049/6072503.
I have sorted this problem with an interesting caveat:
The duplicate Vue package doesn't get imported when the plugin is used via an NPM package (installed by npm install -save <plugin-name> )
However, during development, if you use the package vie npm link (like npm link <plugin-name>) then Vue gets imported twice, like shown in that image in the original question.
People who encounter similar problems in the future, please try to publish and import your package and see if it makes any difference.
Thank you!

Can't add directive as plugin in Nuxt application

I'm trying to incorporate the Ripple package into my Nuxt application.
Following Nuxt docs and the package docs example I have a ripple.js file in plugins/ directory containing this:
import Vue from 'vue'
import Ripple from 'vue-ripple-directive'
Vue.directive('ripple', Ripple)
Then in nuxt.config.js I have:
plugins: [
'~/plugins/ripple.js'
],
But now the app doesn't work at all, with some Unexpected token export error message on the screen, and a "Missing stack frames" error message in vm.js.
I have no idea what that means nor what I'm doing wrong, any suggestion?
This is due to an SSR error, where vue-ripple-directive cannot be used on the server. In order to get around this, you need to instruct Nuxt to only load the plugin on the client side.
To fix this, do the following 2 things:
First, rename ripple.js to ripple.client.js.
Second, update the plugins array to the following:
plugins: [
'~/plugins/ripple.client.js'
]
The .client postfix signals to nuxt to only run the plugin on the client.
More information can be found here
Always keep this method in mind when adding Vue plugins, especially when they interact with the DOM in some way. Most that I've come across require this method to function without errors, as the DOM is unavailable on the server.

process.env.NODE_ENV is not working with webpack3 [duplicate]

I've got an existing code base in which Vue.js has performance problems. I also see this notice in the browser console:
so I guess an easy fix could be to put Vue into production mode.
In the suggested link I try to follow the instructions for webpack. We're on Webpack version 2.7 (current stable version is 4.20). In the instructions it says that in Webpack 3 and earlier, you’ll need to use DefinePlugin:
var webpack = require('webpack')
module.exports = {
// ...
plugins: [
// ...
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
}
So in my package.json I've got a build script defined:
To build for production I run yarn run build and it runs a build.js file (paste here) which in turn calls webpack.base.conf.js (paste here) and webpack.prod.conf.js (paste here).
As you can see in the paste I use the DefinePlugin as suggested by the docs.
I also found a file called vue-loader.conf.js (paste here) and to be sure I also added the DefinePlugin in there as well.
I can run yarn run build which ends without errors, but when serve the site over Apache and open the browser it still shows the notification that we're in development mode.
To be sure it actually uses the files created by webpack I completely removed the folder /public/webpack/ and checked that the webinterface didn't load correctly without the missing files and then built again to see if it loaded correctly after the command finished. So it does actually use the files built by this webpack process. But Vue is actually not created in production mode.
What am I doing wrong here?
The problem may be in your 'webpack.base.conf.js' as i suspected, thank you for sharing it, upon searching i've found an issue resolving your 'production not being detected' problem on github here
The solution requires that you change 'vue$': 'vue/dist/vue' to 'vue$': vue/dist/vue.min in production.
You will find the original answer as:
#ozee31 This alias 'vue$': 'vue/dist/vue' cause the problem, use vue/dist/vue.min in production environment.