At first, I created a vuestorefront nuxtjs project using the command
npx @vue-storefront/cli generate store
with Odoo integration
After that, I created a .env
file
BASE_URL=http://localhost:8069/
SITE_URL=http://localhost:3000/
# PUBLIC_PATH=https://xyz.cloudfront.cdn.com
# For CI and other deployment scripts
NODE_ENV=dev
NODE_LOCALE=en-EN
PORT=3000
HOST=0.0.0.0
#REDIS_ENABLED=false
#REDIS_HOST=127.0.0.1
#REDIS_PORT=6379
#REDIS_PASSWORD=pass
# Used for invalidating cache
# INVALIDATION_KEY={get one and add here and inside Odoo}
#NUXT_TELEMETRY_DISABLED=1
#GOOGLE_TAG_MANAGER_ID=1
After that
yarn
yarn dev
It’s showing now
Error
Must use import to load ES Module: ~/vsfdemo/node_modules/@glidejs/glide/dist/glide.js require() of ES modules is not supported. require() of /home/mohiuddin/vsfdemo/node_modules/@glidejs/glide/dist/glide.js from ~/node_modules/vue-server-renderer/build.dev.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename glide.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from ~/vsfdemo/node_modules/@glidejs/glide/package.json
After searching online for many hours I have changed my nuxt.config.js from
transpile: ['vee-validate/dist/rules'],
to
transpile: ['vee-validate/dist/rules', '@glidejs/glide'],
Now it’s showing
TypeError
Cannot read property '$i18n' of undefined
My nuxt.config.js
file is as follows:
/* eslint-disable camelcase */
import webpack from 'webpack';
import { getRoutes } from './routes';
import getAppRoutes from './sitemap';
import redirects from './customRoutes/redirects.json';
import theme from './themeConfig';
const isDev = process.env.NODE_ENV !== 'production';
export default {
server: {
port: 3000,
host: '0.0.0.0'
},
components: [
'~/components/',
'~/components/Core/Atoms'
],
css: ['@/assets/styles.scss'],
head: {
title: 'Vue Storefront',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || ''
}
],
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico'
}
]
},
router: {
extendRoutes(routes) {
getRoutes(`${__dirname}`)
.forEach((route) => routes.unshift(route));
},
middleware: ['checkout']
},
googleFonts: {
families: {
Roboto: true,
Montserrat: {
wght: [100, 200, 300, 400, 500, 600, 700, 800, 900]
},
Lato: {
wght: [100, 300, 400, 700, 900]
},
Raleway: {
wght: [100, 200, 300, 400, 500, 600, 700, 800, 900]
}
},
download: false
},
pwa: {
meta: {
name: 'VSF Odoo',
theme_color: '#fff',
lang: 'en',
description: 'VSF Odoo',
twitterCard: 'summary_large_image'
},
manifest: {
name: 'VSF Odoo',
description: 'VSF Odoo',
short_name: 'VSFOdoo',
lang: 'en'
},
icon: {
purpose: 'maskable'
},
workbox: {
cleanupOutdatedCaches: true,
preCaching: [
'/error/error.svg',
'/icons/*',
'/favicon.ico'
]
}
},
device: {
refreshOnResize: true
},
loading: { color: '#fff' },
plugins: [
'~/plugins/getImage.ts',
'~/plugins/vee-validate.ts'
],
buildModules: [
// to core
'@nuxtjs/composition-api/module',
'@nuxtjs/pwa',
'@nuxt/image',
'@nuxtjs/device',
'@nuxtjs/web-vitals',
'@nuxtjs/tailwindcss',
'@nuxt/typescript-build',
'@nuxtjs/style-resources',
'@nuxtjs/google-fonts',
[
'@vue-storefront/nuxt',
{
performance: {
httpPush: true
},
// @core-development-only-start
// @core-development-only-end
useRawSource: {
dev: ['@vue-storefront/odoo', '@vue-storefront/core'],
prod: ['@vue-storefront/odoo', '@vue-storefront/core']
}
}
],
// @core-development-only-start
[
'@vue-storefront/nuxt-theme',
{
routes: false
}
],
// @core-development-only-end
/* project-only-start
['@vue-storefront/nuxt-theme'],
project-only-end */
['@vue-storefront/odoo/nuxt', {}]
],
publicRuntimeConfig: {
theme,
baseURL: process.env.BASE_URL,
siteURL: process.env.SITE_URL
},
modules: [
'@nuxtjs/pwa',
'nuxt-precompress',
'@nuxt/image',
'@vue-storefront/middleware/nuxt',
'nuxt-i18n',
'cookie-universal-nuxt',
'vue-scrollto/nuxt',
['@vue-storefront/cache/nuxt', {
enabled: (process.env.REDIS_ENABLED === 'true') || false,
invalidation: {
endpoint: '/cache-invalidate',
key: '0ead60c3-d118-40be-9519-d531462ddc60',
handlers: [
'@vue-storefront/cache/defaultHandler'
]
},
driver: [
'@vue-storefront/redis-cache',
{
defaultTimeout: 86400,
redis: {
host: process.env.REDIS_HOST || '127.0.0.1',
port: process.env.REDIS_PORT || 6379,
password: process.env.REDIS_PASSWORD || ''
}
}
]
}],
// google tag manager
'@nuxtjs/gtm',
// sitemap generator
'@nuxtjs/sitemap',
// redirect
'@nuxtjs/redirect-module'
],
// google tag manager
gtm: {
id: process.env.GOOGLE_TAG_MANAGER_ID,
enabled: !isDev,
pageTracking: true,
pageViewEventName: 'PageView',
debug: process.env.NODE_ENV !== 'production'
},
// redirect
redirect: {
statusCode: 301,
rules: redirects
},
nuxtPrecompress: {
enabled: !isDev,
report: false,
test: /.(js|css|html|txt|xml|svg)$/,
// Serving options
middleware: {
// You can disable middleware if you serve static files using nginx...
enabled: true,
// Enable if you have .gz or .br files in /static/ folder
enabledStatic: true,
// Priority of content-encodings, first matched with request Accept-Encoding will me served
encodingsPriority: ['br', 'gzip']
},
// build time compression settings
gzip: {
enabled: !isDev,
// compression config
// https://www.npmjs.com/package/compression-webpack-plugin
filename: '[path].gz[query]',
threshold: 10240,
minRatio: 0.8,
compressionOptions: { level: 9 }
},
brotli: {
enabled: !isDev,
// compression config
// https://www.npmjs.com/package/compression-webpack-plugin
filename: '[path].br[query]',
compressionOptions: { level: 11 },
threshold: 10240,
minRatio: 0.8
}
},
i18n: {
baseUrl: process.env.SITE_URL,
strategy: 'prefix_and_default',
currency: 'USD',
country: 'US',
countries: [
{ name: 'US', label: 'United States' },
{ name: 'DE', label: 'Germany' },
{ name: 'RU', label: 'Russian' }
],
currencies: [
{ name: 'EUR', label: 'Euro' },
{ name: 'USD', label: 'Dollar' },
{ name: 'RUB', label: 'Rubble' }
],
locales: [
{
code: 'en',
label: 'English',
file: 'en.json',
iso: 'en'
},
{
code: 'de',
label: 'German',
file: 'de.json',
iso: 'de'
},
{
code: 'ru',
label: 'Russian',
file: 'ru.json',
iso: 'ru'
}
],
defaultLocale: 'en',
lazy: true,
seo: true,
langDir: 'lang/',
vueI18n: {
fallbackLocale: 'en',
numberFormats: {
en: {
currency: {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol'
}
},
de: {
currency: {
style: 'currency',
currency: 'EUR',
currencyDisplay: 'symbol'
}
},
ru: {
currency: {
style: 'currency',
currency: 'RUB',
currencyDisplay: 'symbol'
}
}
}
},
detectBrowserLanguage: {
cookieKey: 'vsf-locale'
}
},
// sitemap options
sitemap: {
hostname: process.env.SITE_URL,
exclude: ['/checkout/**', '/checkout', '/cart', '/my-account', '/order-history'],
i18n: false,
cacheTime: 6000,
gzip: true,
defaults: {
changefreq: 'daily',
priority: 1,
lastmod: new Date()
},
routes: getAppRoutes,
filter: ({ routes }) => {
return routes.filter(route => {
return route.path?.toLowerCase() === route.path;
});
}
},
styleResources: {
scss: [
require.resolve('@storefront-ui/shared/styles/_helpers.scss', {
paths: [process.cwd()]
})
]
},
build: {
//standalone: true,
babel: {
plugins: [
['@babel/plugin-proposal-private-property-in-object', { loose: true }]
]
},
postcss: {
plugins: {
'postcss-custom-properties': false
}
},
transpile: ['vee-validate/dist/rules', '@glidejs/glide'],
extend(config, ctx) {
if (ctx.isDev) {
config.devtool = ctx.isClient ? 'source-map' : 'inline-source-map';
}
},
plugins: [
new webpack.DefinePlugin({
'process.VERSION': JSON.stringify({
// eslint-disable-next-line global-require
version: require('./package.json').version,
lastCommit: process.env.LAST_COMMIT || ''
})
})
]
}
};
the package.json
file is as follows:
{
"name": "@vue-storefront/odoo-theme",
"version": "1.1.0",
"private": true,
"scripts": {
"build": "cross-var nuxt build -m --dotenv $VSF_RC",
"build:local": "nuxt build -m --dotenv .env",
"test:e2e": "cypress open --config-file tests/e2e/cypress.json",
"test:e2e:hl": "cypress run --headless --config-file tests/e2e/cypress.json",
"build:analyze": "nuxt build -a -m",
"cypress:open": "cypress open",
"dev": "nuxt dev",
"generate": "nuxt generate",
"start": "nuxt start",
"update:check": "ncu",
"update:update": "ncu -u",
"update:routes": "node hooks/execute.js routes",
"update:redirects": "node hooks/execute redirects",
"test": "jest"
},
"dependencies": {
"@adyen/adyen-web": "^5.23.1",
"@nuxt/image": "^0.6.1",
"@nuxt/types": "latest",
"@nuxtjs/amp": "^0.5.4",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/device": "^2.1.0",
"@nuxtjs/google-fonts": "^2.0.0",
"@nuxtjs/gtm": "^2.4.0",
"@nuxtjs/pwa": "^3.3.5",
"@nuxtjs/redirect-module": "^0.3.1",
"@nuxtjs/sitemap": "^2.4.0",
"@nuxtjs/style-resources": "1.1.0",
"@nuxtjs/tailwindcss": "^4.1.3",
"@nuxtjs/web-vitals": "^0.1.8",
"@storefront-ui/vue": "0.13.3",
"@vue-storefront/cache": "^2.6.0",
"@vue-storefront/middleware": "2.5.4",
"@vue-storefront/nuxt": "2.5.4",
"@vue-storefront/nuxt-theme": "2.5.4",
"@vue-storefront/odoo": "1.4.0",
"@vue-storefront/redis-cache": "^1.0.1",
"cookie-universal-nuxt": "^2.1.3",
"core-js": "^2.6.5",
"cross-var": "^1.1.0",
"nuxt": "^2.15.8",
"nuxt-i18n": "^6.5.0",
"nuxt-precompress": "^0.5.9",
"redis-tag-cache": "^1.2.1",
"vee-validate": "^3.2.3",
"vue-i18n": "8",
"vue-scrollto": "^2.17.1",
"vue-server-renderer": "^2.7.13"
},
"devDependencies": {
"@nuxt/typescript-build": "latest",
"@vue/test-utils": "^1.0.0-beta.27",
"autoprefixer": "^10.2.6",
"babel-jest": "^24.1.0",
"cypress": "7.5.0",
"lint-staged": "^11.1.2",
"nuxt-vite": "^0.3.5",
"postcss": "^8.3.5",
"tailwindcss": "^2.1.4",
"vue-cli-plugin-tailwind": "~2.0.6",
"vue-jest": "^4.0.0-0"
}
}
Sorry if the way of questioning is wrong. I am completely stuck with this problem. I am completely new to NuxtJS and VueJS
node version: v14.20.1
npm version: 6.14.17
Nuxt version: v2.15.8
yarn: v1.22.19
Here is the given Vue file
<template>
<div class="container">
<SfButton
class="container__lang container__lang--selected"
@click="isLangModalOpen = !isLangModalOpen"
>
<SfImage
:height="20"
:width="20"
:src="addBasePath(`/icons/langs/${locale}.webp`)"
alt="Flag"
class="language__flag"
/>
</SfButton>
<SfBottomModal
:is-open="isLangModalOpen"
title="Choose language"
@click:close="isLangModalOpen = !isLangModalOpen"
>
<SfList>
<SfListItem v-for="lang in availableLocales" :key="lang.code">
<a :href="switchLocalePath(lang.code)" @click="$i18n.setLocale(lang.code)">
<SfCharacteristic class="language">
<template #title>
<span>{{ lang.label }}</span>
</template>
<template #icon>
<SfImage
:src="addBasePath(`/icons/langs/${lang.code}.webp`)"
:width="20"
:height="20"
alt="Flag"
class="language__flag"
/>
</template>
</SfCharacteristic>
</a>
</SfListItem>
</SfList>
</SfBottomModal>
</div>
</template>
<script>
import {
SfImage,
SfSelect,
SfButton,
SfList,
SfBottomModal,
SfCharacteristic
} from '@storefront-ui/vue';
import { ref, computed } from '@nuxtjs/composition-api';
import { addBasePath } from '@vue-storefront/core';
export default {
components: {
SfImage,
SfSelect,
SfButton,
SfList,
SfBottomModal,
SfCharacteristic
},
setup(props, context) {
const { locales, locale } = context.root.$i18n;
const isLangModalOpen = ref(false);
const availableLocales = computed(() =>
locales.filter((i) => i.code !== locale)
);
return {
availableLocales,
locale,
isLangModalOpen,
addBasePath
};
}
};
</script>
2
Answers
In your
nuxt.config.js
file, you made a typo in themodules
section.Here is the correct name of the module
Here is the link in the doc: https://i18n.nuxtjs.org/setup
The rest works fine on my side, I didn’t face any other issues by replicating your setup.
I had the same error. After building and deploying VSF, i got the Server Error
What solved my issue was setting the version to
3.5.2
in thepackage.json
as resolution"resolutions": { "@glidejs/glide": "3.5.2" }
as mentioned here https://github.com/vuestorefront/storefront-ui/issues/2494
Another way is to set
to
2.7.5
that also solves the problem