How to set up plotly.js in nuxt SSR? - javascript

I'm trying to set up plotly.js in nuxt but whatever I do I get this cryptic error
self is not defined
I tried to install plotly.js and plotly.js-dist same error shows.
I would prefer to make custom build so I tried like this in nuxt plugins:
// here we use custom partial bundle
import plotly from 'plotly.js/lib/core';
import barpolar from 'plotly.js/lib/barpolar';
export default function (_, inject) {
plotly.register([barpolar]);
inject('plotly', plotly);
}
but whenever I register nuxt plugin site crashes with aforementioned error.
Even not going down custom bundle route, and using dist lib still fails just the same.
I also tried not to employ nuxt plugins system but to import manually and to set up, same things happen.
I also added ify-loader as recommended here: https://github.com/plotly/plotly-webpack
and this is my nuxt.config.js in regards to webpack plugin:
build: {
extend(config, { isClient }) {
console.log('config :>> ', config);
config.module.rules.push({
test: /\.js$/,
use: [
'ify-loader',
'transform-loader?plotly.js/tasks/compress_attributes.js',
],
});
},
},
still no luck.
I presume this is problem with webpack 5 and plotly.js not working well together in default setup but I have no idea how to solve this.
Help appreciated.

The reason why this wasn't working is that plotly tried to access document, and in SSR that would obviously fail.
So to fix this I just had to assign plugin in client only mode like this:
plugins: [
// other plugins
{ src: '~/plugins/plotly', mode: 'client' },
],
and it worked.

Related

Openlayers in nuxt blob is undefined

I'm trying to make openlayers work in Nuxt but whenever I tried to import openlayers components, I had several errors that I solved, but one of them is "Blob is not defined - node_modules/ol/worker/webgl.js"
I found nothing on openlayers and nuxt and i'm having hard times to just make it work :/
Here is the steps of what I did :
npm install ol
made a file with import View from 'ol/View', got error "can't import ESM module...."
created a plugins folder with a ol.js with all OL assests imported, and added plugins: ['#/plugins/ol'] in nuxt.config
preview of my ol.js file in my plugins folder
Got error "can't read fs" file
added extend: (config, { isDev, isClient }) => { config.node = {fs: 'empty',} into my nuxt.config file in build
Also added standalone: true,
and NOW I have blob is undefined and really, I have no clue on what to do to make openlayers work :/
Any help is welcome !
EDIT : Made some changes
1 I installed vuelayers
2 followed the guide on https://vuelayers.github.io/#/docs/quickstart?id=nuxtjs
edited nuxt.config
plugins: [{
src: '#/plugins/vuelayers.js',
ssr: false
}, { ... }],
modules: [
...,
'~/shared/vueLayers',
],
Create a file shared/ directory named vuelayers.js
export default function (moduleOptions) {
this.options.css.push('vuelayers/lib/style.css')
}
3 pasted the content of the "simple map example"
I have no error but nothing is displayed on my component yet
The "can't import ESM module...." occurs because the ol package exports an ES6 module and when Nuxt is rendered on the server side the parent project uses CommonJS modules. As a result a run time error occurs when the open layers code is not transpiled for server side rendering.
I found there to be two solutions to this problem.
Explicitly transpile the Open Layers modules that are used in the transpile property of the build property in nuxt.config.js
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
transpile: [
'ol/control',
'ol/proj',
'ol/style/Circle',
'ol/style/Fill',
'ol/format/GeoJSON',
'ol/format/MVT',
'ol/Map',
// ...
],
},
Create a Nuxt plug-in to wrap Open Layers that's only used on the client side similar to the example seen in this gist.
I found the second solution to be cleaner and since Open Layers uses <canvas> render the map it can't easily be rendered on the server side anyway.
Note that the Gist linked above is a bit dated, but the idea is still relevant. A modern example might look like the following:
// plugins/open-layers.js
import Map from 'ol/Map';
import View from 'ol/View';
export default (context, inject) => {
const ol = {
Map,
View,
};
inject('ol', ol);
};
// nuxt.config.js
export default {
// ...
plugins: [
{ src: '~/plugins/open-layers.js', mode: 'client' },
],
};
// Parent component
<template>
<client-only>
<Map />
</client-only>
</template>
// Map.vue
<template>
<div ref="map" />
</template>
<script>
export default {
name: 'Map',
methods: {
renderChart() {
this.map = new $ol.Map({
target: this.$refs.map,
view: new $ol.View({}),
});
},
},
};
</script>

Bootstrap 5 with Grunt to bundle and optimise js

I have successfully used Grunt to bundle the bootstrap 5 scss together into a single file. I have it setup so I can add and remove the component scss to the needs of the project for optimisation.
I am now trying to do the same with the js.
I am using grunt-contrib-uglify with the following task:
uglify: {
site: {
options: {
sourcemap: false
},
files: {
'example/static/example/assets/js/example.min.js': [
// popper bs5 dependency
'node_modules/#popperjs/core/dist/umd/popper.js',
// bootstrap 5 core js
'node_modules/bootstrap/js/dist/dom/data.js',
'node_modules/bootstrap/js/dist/dom/event-handler.js',
'node_modules/bootstrap/js/dist/dom/manipulator.js',
'node_modules/bootstrap/js/dist/dom/selector-engine.js',
// component js
// note ordering of components can be important
// eg. popover relies on tooltip, therefore tooltip must therefore go first
'node_modules/bootstrap/js/dist/base-component.js',
'node_modules/bootstrap/js/dist/alert.js',
'node_modules/bootstrap/js/dist/button.js',
'node_modules/bootstrap/js/dist/carousel.js',
'node_modules/bootstrap/js/dist/collapse.js',
'node_modules/bootstrap/js/dist/dropdown.js',
'node_modules/bootstrap/js/dist/modal.js',
'node_modules/bootstrap/js/dist/offcanvas.js',
'node_modules/bootstrap/js/dist/scrollspy.js',
'node_modules/bootstrap/js/dist/tab.js',
'node_modules/bootstrap/js/dist/toast.js',
'node_modules/bootstrap/js/dist/tooltip.js',
'node_modules/bootstrap/js/dist/popover.js',
// custom js
'example/src/js/**/*.js'
]
}
},
},
I include it in my html, then have a script below it eg.
<script>
var myOffcanvas = document.getElementById('offcanvasExample')
var bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
</script>
I get the error:
ReferenceError: bootstrap is not defined
in the console. What am I missing from the bundle to make this work? I have used the npm bs5 starter on Github as a reference for the files eg. popper dependency, the core js and imported all other component files in the node_modules/bootstrap/js/dist folder.
Github Bootstrap 5 npm starter
Bootstrap 5.1
Popper 2.9.2
Edit: Works correctly with distributed bundle.
so using the same grunt uglify task above, you can:
<script>
var myOffcanvas = document.getElementById('offcanvasExample')
var bsOffcanvas = Offcanvas(myOffcanvas)
</script>
(Note the removal of new bootstrap. from the script). I think this is because when importing the component files separately you are not importing Bootstrap as a module. Therefore unlike the bundle it is not available.
However, the components as separate functions are imported and available (much like Offcanvas in the above example)
EDIT
As bootstrap 5 uses rollup to bundle its javascript I have now looked into the 'grunt-rollup' task. I was not happy in the respect that my previous answer did not align with the bootstrap docs.
I have since got it working successfully with the grunt-rollup task with this configuration:
// gruntfile imports
const babel = require("#rollup/plugin-babel").default;
const path = require('path')
const {nodeResolve} = require("#rollup/plugin-node-resolve");
// rollup task
rollup: {
options: {
plugins: [
babel({
exclude: './node_modules/**',
babelHelpers: 'bundled',
}),
nodeResolve()
],
globals: {
'#popperjs/core': 'Popper'
},
external: ['#popperjs/core'],
format: 'umd',
name: 'bootstrap',
},
files: {
src: path.resolve(__dirname, `path/to/bootstrap5/imports/file`),
dest: path.resolve(__dirname, `path/to/export/file`),
},
},
where the bootstrap imports file looks like:
import Alert from 'node_modules/bootstrap/js/src/alert'
import Button from 'node_modules/bootstrap/js/src/button'
import Carousel from 'node_modules/bootstrap/js/src/carousel'
import Collapse from 'node_modules/bootstrap/js/src/collapse'
import Dropdown from 'node_modules/bootstrap/js/src/dropdown'
import Modal from 'node_modules/bootstrap/js/src/modal'
import Offcanvas from 'node_modules/bootstrap/js/src/offcanvas'
import Popover from 'node_modules/bootstrap/js/src/popover'
import ScrollSpy from 'node_modules/bootstrap/js/src/scrollspy'
import Tab from 'node_modules/bootstrap/js/src/tab'
import Toast from 'node_modules/bootstrap/js/src/toast'
import Tooltip from 'node_modules/bootstrap/js/src/tooltip'
export default {
Alert,
Button,
Carousel,
Collapse,
Dropdown,
Modal,
Offcanvas,
Popover,
ScrollSpy,
Tab,
Toast,
Tooltip
}
now you can choose which components to have in the js.
I'm not a super expert and not sure if the question is clear enough, but I would not recommend concatenating Libraries like Boostrap into a single main file in together other JS files outside the framework, due to performance issues and possible crashes in between libs due to definitions, and the possibility to update without a build process and also your site might be penalized by google engine.
Besides that, Boostrap normally already provides .min.css and .min.js already compressed/minified/uglified ready to use if you are not gonna change anything from the original design patterns, avoid using uncompress files if you are not gonna customize it.
for the rest in regards to other custom libraries or vanilla's JS create by you, you can use grunt-contrib-concat also if you wanna check the performance you can use
PageSpeed Insights with the result will know what exactly needs to be applied to get better performance and optimization.

How to install Vuetify correctly if there is no webpack.config.js file?

The Vuetify document says:
Blockquote
Once installed, locate your webpack.config.js file and copy the snippet below into the rules array. If you have an existing sass rule configured, you may need to apply some or all of the changes below. If you are you looking to utilize the vuetify-loader for treeshaking, ensure that you are on version >=4 of Webpack. You can find more information on setting it up with webpack on the A-la-carte page.
// webpack.config.js
module.exports = {
rules: [
{
test: /\.s(c|a)ss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
// Requires sass-loader#^7.0.0
options: {
implementation: require('sass'),
fiber: require('fibers'),
indentedSyntax: true // optional
},
// Requires sass-loader#^8.0.0
options: {
implementation: require('sass'),
sassOptions: {
fiber: require('fibers'),
indentedSyntax: true // optional
},
},
},
],
},
],
}
However, there is no webpack.config.js in my project. And I did create my project using webpack.
Could anyone tell me where should I add the specified code into?
Thanks!
Edited:
The reason why I need to add the mentioned code is that I encountered an error:
webpack-internal:///./node_modules/vue/dist/vue.esm.js:629 [Vue warn]: Error in render: "TypeError: Cannot read property 'smAndDown' of undefined" found in ---> <VToolbar> <VCard> <StudentInfo> at src/components/StudentInfo.vue <App> at src/App.vue <Root>
I googled it and it is said it is because Vuetify is not installed correctly.
Please take a look at this link, which my problematic file:
https://github.com/powerseed/Test/blob/master/client/src/components/StudentInfo.vue
The v-toolbar is the part that causes the error. And if you remove it, the error disappears.
I think if I add the mentioned code into webpack.congif.js, it may solve the error, because it is the only part on the Vuetify document that I didn't do. Otherwise I don't know how to solve it...
I have also had difficulty trying to 'vue add vuetify' to my project retrospectively. From now on, when I start a new project I install it from the beginning. If your project is already in dev, you could try doing it via the vue GUI, I've done that in the past for existing projects and had no issues with them breaking.
My solution to using vuetify has always been to do the following in your src/main.js
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify) //Add any theme modifications here
Check out https://vuetifyjs.com/en/getting-started/quick-start/ just below where you found the webpack.config.js
You can set it up using a plugin.js like how it is done in the documentation or how I have above. In my example the webpack.config is not needed!

Webpack inter-library dependency as in requireJS.config.shim

I am converting a grunt + requireJS build process to webpack. We have something like this:
require.config({
shim:{
'popover': {
deps: ['tooltip']
},
'tooltip': {
deps: ['jquery']
}
}
})
Where we are specifically saying that tooltip depends on jquery so load jquery first. Popover depends on tooltip so load tooltip beforehand.
How do I translate this configuration into webpack 4 ? I've searched through the web trying to see if there are anything similar enough. Webpack's shimming doesn't do inter-library dependency. I don't see anything in the documentation too ...which surprised me much.
I have find articles (https://gist.github.com/xjamundx/b1c800e9282e16a6a18e)
that suggest of use import-loader to achieve such effect. So my config is like this:
module:{
strictExportPresence:true,
rules:[
{ parser: { requireEnsure: false } },
{ oneOf:[...bunch of stuffs for different file types] },
{ test : /tooltip/, loader: 'imports-loader?$=jquery' },
{ test : /popover/, loader: 'imports-loader?tooltip' }
]
also have the appropriate aliases in config set up.
the error I am getting it the browser is Constructor undefined on line
"Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype ..."
so tooltip library isn't being loaded before popover is.
I also don't see any new code added by webpack, which I think this could be my first problem since imports-loader supposedly add the specified library into popover module right ?
I am exactly seeing what's wrong with my approach anymore and exhausted a lot of resources online. I am sure someone had to deal with this type of problem before, please shade some light for me. Thanks!
You should provide tooltip and popover in resolve.alias section:
resolve: {
alias: {
"jquery": "lib/jquery-x.x.x",
"tooltip": "lib/tooltip-x.x.x",
"popover": "lib/popover-x.x.x"
}
}
Otherwise webpack won't be able to resolve modules to shim by imports-loader. Also, please note that you misspelled imports-loader in your configuration.

How can I transpile a dependency in node_modules with Nuxt 2?

I have read of issues with transpiling node_modules with Nuxt, but the new Nuxt 2 is said to have solved this with a transpile option in the nuxt.config.js file.
https://nuxtjs.org/api/configuration-build/#transpile
Here is what I have:
export default {
router: {
base: '/',
},
build: {
transpile: [
'choices.js',
'lazysizes',
'swiper',
'vee-validate'
],
extractCSS: true
},
srcDir: 'src/',
performance: {
gzip: true
},
render: {
compressor: {
threshold: 100
}
},
dev: false
}
I removed a few things that are unrelated to make it easier to read.
When I run npm run build (nuxt build) the compiled JS files contain references to es6 and es7 code such as const and let etc when it should be var.
I have isolated this issue to be coming from Swiper. It appears to internally depend on something called Dom7 that seems to be causing the problem.
I am wanting to compile these node_modules dependencies to es5 if possible. I'm not sure my current setup is actually doing anything at all in that regard.
I believe Nuxt uses vue-app for Babel, but I even tried the following to no success:
babel: {
presets: [
'#babel/preset-env'
],
plugins: [
'#babel/plugin-syntax-dynamic-import'
]
}
Not much joy there either. Nothing appears differently in the final build.
I am using Nuxt 2.1.0
Any help appreciated. Thanks!
You also need to transpile Dom7, so the Nuxt config should have:
build: {
transpile: [
'swiper',
'dom7',
],
}
I have the exact same issue.
The vendor option under build is deprecated, so it's simply ignored I believe from what I read here https://medium.com/nuxt/nuxt-2-is-coming-oh-yeah-212c1a9e1a67#a688
I managed to isolate my case to the "swiper" library. If I remove that from my project, all references to let, const or class are gone. I've tried the transpile option too, but it does not seem to have any effect.
Will you try to exclude swiper from your project to see if we can isolate the issue?

Categories

Resources