vue laravel | GTM Integration - laravel

Well I have a Laravel Vue setup.
Package.json
{
"devDependencies": {
"axios": "^0.15.3",
"babel-preset-es2015": "^6.24.1",
"bootstrap": "4.0.0-beta",
"cross-env": "^3.2.3",
"jquery": "^3.1.1",
"laravel-mix": "1.2.0",
"lodash": "^4.17.4",
"vue": "^2.4.2"
},
"dependencies": {
"favico.js": "^0.3.10",
"intersection-observer": "^0.5.0",
"laravel-echo": "^1.3.2",
"moment-timezone": "^0.5.14",
"popper.js": "^1.12.2",
"pusher-js": "^4.2.1",
"sweetalert2": "^6.6.8",
"vue-image-crop-upload": "^1.3.15",
"vue-moment": "^2.0.2",
"vue-multiselect": "2.0.2",
"vue-observe-visibility": "^0.3.1",
"vue-switches": "^1.1.7",
"vue-template-compiler": "^2.4.2"
}
}
I am trying to integrate GTM. I could have used vue-gtm but since I am not using vue-router Its really hard to configure. I am using Laravel routes.
Any solutions to integrate it?
If anyone know how to integrate spatie/laravel-googletagmanager with vue .. Please help me out.

vue-gtm does not require the router. it just automates it and makes it easier, it doesn't mean you have to do this.
import VueGtm from 'vue-gtm';
import VueRouter from 'vue-router';
const router = new VueRouter({ routes, mode, linkActiveClass });
Vue.use(VueGtm, {
id: 'GTM-xxxxxxx', // Your GTM ID
enabled: true, // defaults to true. Plugin can be disabled by setting this to false for Ex: enabled: !!GDPR_Cookie (optional)
debug: true, // Whether or not display console logs debugs (optional)
vueRouter: router, // Pass the router instance to automatically sync with router (optional)
ignoredViews: ['homepage'] // If router, you can exclude some routes name (case insensitive) (optional)
});
You can completely disregard adding the vueRouter and ignoredViews parameters above.
Then in your components that need to dispatch events:
this.$gtm.trackEvent({
event: null, // Event type [default = 'interaction'] (Optional)
category: 'Calculator',
action: 'click',
label: 'Home page SIP calculator',
value: 5000,
noninteraction: false // Optional
});
You can figure that function on any action. Page load, click, form submission, etc. Just change the properties to meet your needs.

Related

React Native Web implement SSR

https://necolas.github.io/react-native-web/docs/rendering/
After reading the SSR example from the document, I still don't know how to implement SSR
And I don't want to apply SSR with other framework like NextJS
Can anyone show me an example or give me some advice
I'm posting this, not as a direct answer to the original question, because it's targeted directly SSR with NextJS, and the OP needed SSR independently from frameworks like NextJS. However, understanding it with NextJS can get anyone closer with things, because they key relies in Webpack config that NextJS also use as SSR in its encapsulation config.
First thing to know is that, once a Package has been written for React Native, it need to be transpiled first to be able to be used in Web, with webpack config.externals.
let modulesToTranspile = [
'react-native',
'react-native-dotenv',
'react-native-linear-gradient',
'react-native-media-query',
'react-native-paper',
'react-native-view-more-text',
// 'react-native-vector-icons',
];
Then you need to alias some react-native packages to react-native-web equivalent to let package use web version of modules like:
config.resolve.alias = {
...(config.resolve.alias || {}),
// Transform all direct `react-native` imports to `react-native-web`
'react-native$': 'react-native-web',
'react-native-linear-gradient': 'react-native-web-linear-gradient',
};
At this point, you almost get the essential. The rest is normal Webpack config for the normal Application. Also, it needs some additional config in native config file too. I will post all configs content.
For NextJS: next.config.js :
const path = require('path');
let modulesToTranspile = [
'react-native',
'react-native-dotenv',
'react-native-linear-gradient',
'react-native-media-query',
'react-native-paper',
'react-native-view-more-text',
// 'react-native-vector-icons',
];
// console.log('modules to transpile', modulesToTranspile);
// import ntm = from 'next-transpile-modules';
// const withTM = ntm(modulesToTranspile);
// logic below for externals has been extracted from 'next-transpile-modules'
// we won't use this modules as they don't allow package without 'main' field...
// https://github.com/martpie/next-transpile-modules/issues/170
const getPackageRootDirectory = m =>
path.resolve(path.join(__dirname, 'node_modules', m));
const modulesPaths = modulesToTranspile.map(getPackageRootDirectory);
const hasInclude = (context, request) => {
return modulesPaths.some(mod => {
// If we the code requires/import an absolute path
if (!request.startsWith('.')) {
try {
const moduleDirectory = getPackageRootDirectory(request);
if (!moduleDirectory) {
return false;
}
return moduleDirectory.includes(mod);
} catch (err) {
return false;
}
}
// Otherwise, for relative imports
return path.resolve(context, request).includes(mod);
});
};
const configuration = {
node: {
global: true,
},
env: {
ENV: process.env.NODE_ENV,
},
// optimizeFonts: false,
// target: 'serverless',
// bs-platform
// pageExtensions: ['jsx', 'js', 'bs.js'],
// options: { buildId, dev, isServer, defaultLoaders, webpack }
webpack: (config, options) => {
// config.experimental.forceSwcTransforms = true;
// console.log('fallback', config.resolve.fallback);
if (!options.isServer) {
// We shim fs for things like the blog slugs component
// where we need fs access in the server-side part
config.resolve.fallback.fs = false;
} else {
// SSR
// provide plugin
config.plugins.push(
new options.webpack.ProvidePlugin({
requestAnimationFrame: path.resolve(__dirname, './polyfills/raf.js'),
}),
);
}
// react-native-web
config.resolve.alias = {
...(config.resolve.alias || {}),
// Transform all direct `react-native` imports to `react-native-web`
'react-native$': 'react-native-web',
'react-native-linear-gradient': 'react-native-web-linear-gradient',
};
config.resolve.extensions = [
'.web.js',
'.web.ts',
'.web.tsx',
...config.resolve.extensions,
];
config.externals = config.externals.map(external => {
if (typeof external !== 'function') {
return external;
}
return async ({ context, request, getResolve }) => {
if (hasInclude(context, request)) {
return;
}
return external({ context, request, getResolve });
};
});
const babelLoaderConfiguration = {
test: /\.jsx?$/,
use: options.defaultLoaders.babel,
include: modulesPaths,
// exclude: /node_modules[/\\](?!react-native-vector-icons)/,
};
babelLoaderConfiguration.use.options = {
...babelLoaderConfiguration.use.options,
cacheDirectory: false,
// For Next JS transpile
presets: ['next/babel'],
plugins: [
['react-native-web', { commonjs: true }],
['#babel/plugin-proposal-class-properties'],
// ['#babel/plugin-proposal-object-rest-spread'],
],
};
config.module.rules.push(babelLoaderConfiguration);
return config;
},
};
// module.exports = withTM(config);
module.exports = configuration;
SSR will fail to build when missing some functions at server side. The most popular with React Native is requestAnimationFrame. I added it add a Webpack Plugin to mimic it. It can be an empty function or Polyfill:
The file 'polyfills/raf.js(I just put it assetImmediate`):
const polys = { requestAnimationFrame: setImmediate };
module.exports = polys.requestAnimationFrame;
The Babel config is necessary for the last part of it, couldn't work directly in next config. babel.config.js :
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [['module:react-native-dotenv'], 'react-native-reanimated/plugin'],
};
And finally, my list of packages in package.json:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"android": "react-native run-android",
"android:dev": "adb reverse tcp:8081 tcp:8081 && react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint .",
"web": "webpack serve -d source-map --mode development --config \"./web/webpack.config.js\" --inline --color --hot",
"build:web": "webpack --mode production --config \"./web/webpack.config.js\" --hot",
"next:dev": "next",
"next:build": "next build",
"next:start": "next start",
"next:analyze": "ANALYZE=true next build"
},
"dependencies": {
"#material-ui/core": "^4.12.4",
"#react-native-async-storage/async-storage": "^1.17.3",
"#react-navigation/drawer": "^6.4.1",
"#react-navigation/native": "^6.0.10",
"#react-navigation/stack": "^6.2.1",
"#reduxjs/toolkit": "^1.8.1",
"axios": "^0.21.1",
"local-storage": "^2.0.0",
"lottie-ios": "^3.2.3",
"lottie-react-native": "^5.1.3",
"lottie-web": "^5.9.4",
"moment": "^2.29.1",
"next": "^12.1.6",
"nookies": "^2.5.2",
"numeral": "^2.0.6",
"raf": "^3.4.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-native": "0.68.1",
"react-native-dotenv": "^2.5.5",
"react-native-gesture-handler": "^2.4.2",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-linear-gradient": "^2.5.6",
"react-native-media-query": "^1.0.9",
"react-native-paper": "^4.12.1",
"react-native-progress": "^5.0.0",
"react-native-read-more-text": "^1.1.2",
"react-native-reanimated": "^2.8.0",
"react-native-safe-area-context": "^4.2.5",
"react-native-screens": "^3.13.1",
"react-native-share-menu": "^6.0.0",
"react-native-svg": "^12.3.0",
"react-native-svg-transformer": "^1.0.0",
"react-native-vector-icons": "^9.1.0",
"react-native-view-more-text": "^2.1.0",
"react-native-web": "^0.17.7",
"react-native-web-linear-gradient": "^1.1.2",
"react-redux": "^8.0.1"
},
"devDependencies": {
"#babel/plugin-proposal-class-properties": "^7.14.5",
"#next/bundle-analyzer": "^12.2.2",
"#react-native-community/eslint-config": "^2.0.0",
"#swc/cli": "^0.1.57",
"#swc/core": "^1.2.179",
"eslint": "^7.28.0",
"metro-react-native-babel-preset": "^0.66.0",
"url-loader": "^4.1.1",
"webpack": "^5.39.1",
"webpack-cli": "^4.7.2"
},
"jest": {
"preset": "react-native-web"
},
"sideEffects": false
}
NB: only React-Native packages used also in Web has to be transpiled. Some React-Native packages can be used ONLY in Native, so transpiling them for Web will add up unnecessary chunks of heavy codes in the Web, which is not good. React-Native-Web/React-Native is already more heavy for Web than normal packages made directly for Web.
TIPS to keep it cool with NextJS
Avoid writing conditional Platform.OS === 'web' on small components where you plan to use either a React-Native module or a Web module, which can cause all of them to load unnecessary Native-Only package on web codes. If size is not important, then you can ignore it. Add extension .web.js and .native.js at the end and separate the small codes. For example I write separate Functions and Components for : Storage.web.js, Storage.native.js, CustomLink.web.js, CustomLink.native.js, and hooks useCustomNavigation.web.js, useCustomNavigation.native.js, so that I call CustomLink in place of NextJS Link/router and React-Navigation Link/navigation.
I use react-native-media-query package as life saver for advanced media queries for all SSR/CSR Web and Native responsive display. The App can be restructured on big screen like normal Desktop Web, and be shrunk to Mobile View on the go, EXACTLY LIKE Material-UI on NextJS.

How to instantiate a vue 3 application within Laravel without using a parent App.vue?

I am working in a Laravel 8.x application and have had vue 2.6.12 installed for the longest time. I am working on upgrading to use Vue 3 with laravel and am using with Webpack. I have updated my package.json scripts and have the following installed for Vue 3 compatability:
{
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production"
},
"devDependencies": {
"bootstrap": "^4.5.2",
"jquery": "^3.4",
"laravel-mix": "^6.0.39",
"laravel-mix-polyfill": "^2.0.0",
"vue-loader": "^16.8.3"
},
"dependencies": {
"#vue/compiler-sfc": "^3.2.24",
"jquery-validation": "^1.17.0",
"jquery.nicescroll": "^3.7.6",
"jquery.scrollto": "^2.1.2",
"mdb-vue-ui-kit": "^1.7.0",
"sass": "^1.21.0",
"sass-loader": "^7.1.0",
"vue": "^3.2.24",
"vue-moment": "^4.1.0",
"vue-router": "^4.0.12",
"vue-template-compiler": "^2.6.14",
}
}
I never had a main App.vue file as this started as a Laravel app and Vue was brought in later. Instead I have created (with vue 2 and vue3 now) the initial vue object in my /resources/js/app.js file. This just keyed off of a <div id="app"> located in my parent blade.php file. But now with Vue 3 I am unsure how to do this without manually adding an App.vue file. Is this needed or is there something else I can do to configure vue 3 instantiation in my Laravel app?
Vue 2 setup (working)
const router = new VueRouter({
mode: 'history',
routes: routes
});
const app = new Vue({
el: '#app',
router
});
Vue 3 instantiation attempt
import Vue, {createApp } from 'vue';
import router from './router/routes.js';
const app = new Vue({});
createApp(app)
.use(router)
.use(require('vue-moment'))
.use(VueToast)
.mount('#app')
Main error I get when running npm run dev
WARNING in ./resources/js/app.js 50:14-17
export 'default' (imported as 'Vue') was not found in 'vue' (possible exports: BaseTransition, Comment, EffectScope, Fragment, KeepAlive, ReactiveEffect, Static, Suspense, Teleport, Text, Transition, TransitionGroup, VueElement, callWithAsyncErrorHandling, callWithErrorHandling, camelize, capitalize, cloneVNode, compatUtils, compile, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createHydrationRenderer, createPropsRestProxy, createRenderer, createSSRApp, createSlots, createStaticVNode, createTextVNode, createVNode, customRef, defineAsyncComponent, defineComponent, defineCustomElement, defineEmits, defineExpose, defineProps, defineSSRCustomElement, devtools, effect, effectScope, getCurrentInstance, getCurrentScope, getTransitionRawChildren, guardReactiveProps, h, handleError, hydrate, initCustomFormatter, initDirectivesForSSR, inject, isMemoSame, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isVNode, markRaw, mergeDefaults, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, ssrUtils, stop, toDisplayString, toHandlerKey, toHandlers, toRaw, toRef, toRefs, transformVNodeArgs, triggerRef, unref, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, useTransitionState, vModelCheckbox, vModelDynamic, vModelRadio, vModelSelect, vModelText, vShow, version, warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withKeys, withMemo, withModifiers, withScopeId)
You can register global components to the app you are creating.
import {createApp, defineComponent } from 'vue';
import router from './router/routes.js';
import MyComponent from '#/components/MyComponent.vue'
// Root vue component
const root = defineComponent({/* ... */})
//Create the app
const app = createApp(root)
//Configure the app
app.use(router)
.use(require('vue-moment'))
.use(VueToast)
//Attach global components to the app
app.component('my-component', MyComponent)
//Mount the app
app.mount('#app')

NestJS and Apollo Federation: buildFederatedSchema is deprecated

I am working with NestJS and Apollo Federation for a while and it seems that since last update I get
"(node:19113) DeprecationWarning: 'buildFederatedSchema' is deprecated. Use 'buildSubgraphSchema' instead."
I don't see a place where I could use buildSubgraphSchema and I didn't find anywhere from NestJS docs of Apollo Federation docs a way to remove this deprecated issue.
The full list of dependencies in my package json are
"dependencies": {
"#apollo/federation": "^0.33.3",
"#apollo/subgraph": "^0.1.2",
"#nestjs/common": "^8.0.0",
"#nestjs/config": "^1.0.2",
"#nestjs/core": "^8.0.0",
"#nestjs/graphql": "^9.1.1",
"#nestjs/mongoose": "^9.0.1",
"#nestjs/platform-express": "^8.0.0",
"apollo-server-express": "^3.4.0",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"graphql": "^15.6.1",
"helmet": "^4.6.0",
"joi": "^17.4.2",
"mongoose": "^6.0.12",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},
The GraphQL module is defined in a file called graphql.module.ts with the following:
import { Module } from '#nestjs/common';
import { GraphQLFederationModule } from '#nestjs/graphql';
import { ApolloServerPluginInlineTraceDisabled } from 'apollo-server-core';
#Module({
imports: [
GraphQLFederationModule.forRoot({
plugins: [ApolloServerPluginInlineTraceDisabled()],
autoSchemaFile: true,
playground: true,
introspection: true,
buildSchemaOptions: {
dateScalarMode: 'isoDate',
},
context: ({ req }) => ({
jwt: req.headers.authorization,
}),
}),
],
})
export class GraphqlModule {}
Project still runs normally with the deprecated message but I would be keen to understand how to fix it.
Thanks in advance,
SOLUTION: 2020-03-10
Based on Brando J answer, the next update of nestjs/graphql from version 9 to version 10 fix the issue
The cause of this warning comes from #nestjs/graphql v9 which still use "buildFederatedSchema" from #apollo/federation.
You can update to #nestjs/graphql v10 to get rid of that message. Also GraphQLFederationModule has been removed and replaced by GraphQLModule using ApolloFederationDriver.
tl;dr
update #nestjs/graphql to v10
read this docs to adjust your code to new version https://docs.nestjs.com/graphql/migration-guide

Issue while trying to import socket.io in vue.js component in Laravel

I am using Laravel 5.8 with inbuilt vue.js component and socket.io without using redis and laravel-echo-server
npm installation
npm install vue-socket.io
resources/js/app.js file in Laravel
import VueSocketio from 'vue-socket.io';
Vue.use(VueSocketio);
There is no error when compiled using npm run watch command. When I check the output in browser, there is following error.
Cannot call a class as a function
Issue comes in this line: Vue.use(VueSocketio);
Can you please suggest?
Below is Package.json file
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.1.0",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.5",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.15.2",
"sass-loader": "^7.1.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10",
"vue-vpaginator": "^1.0.0"
},
"dependencies": {
"bootstrap-vue": "^2.0.0-rc.24",
"vee-validate": "^2.2.11",
"vue-chat-scroll": "^1.3.5",
"vue-recaptcha": "^1.2.0",
"vue-socket.io": "^3.0.7",
"vuejs-dialog": "^1.4.0"
}
Node.js side code. This is a complete different working directory from Laravel
const express = require("express");
class Server {
constructor() {
this.app = express();
this.port = process.env.PORT || 89;
this.host = process.env.HOST || `192.168.43.173:89`;
}
includeRoutes() {
}
appExecute() {
var server = this.app.listen(this.port, () => {
console.log(`Listening on http://${this.host}`);
});
}
}
const server = new Server();
server.appExecute();
Update code as per suggested by Javas
Vue.use(new VueSocketio({
debug: true,
connection: 'http://192.168.43.173:89',
}));
You should add a new keywoard before VueSocketio.
Vue.use(new VueSocketio({}));
Don't forget to specify a list of options.

Rollup with #types/d3 using Visual Studio Code

My library project uses...
Typescript
Rollup
D3
#types/d3
The package.json file has these dependencies
"dependencies": {
"#types/d3": "^4.4.0" /* also tried moving this to devDeps */
},
"devDependencies": {
"cssnano": "^3.10.0",
"postcss-cssnext": "^2.9.0",
"postcss-nested": "^1.0.0",
"postcss-simple-vars": "^3.0.0",
"rollup": "^0.40.1",
"rollup-plugin-commonjs": "^7.0.0",
"rollup-plugin-livereload": "^0.4.0",
"rollup-plugin-node-resolve": "^2.0.0",
"rollup-plugin-postcss": "^0.2.0",
"rollup-plugin-serve": "^0.1.0",
"rollup-plugin-typescript": "^0.8.1",
"rollup-plugin-uglify": "^1.0.1",
"rollup-watch": "^3.1.0"
}
My rollup.config.js file has these plugins configured...
plugins: [
typescript(),
postcss({
extension: ['.css'],
plugins: [
simplevars(),
nested(),
cssnext({ warnForDuplicates: false }),
cssnano(),
],
}),
nodeResolve({
jsnext: true, //use jsnext if the node package supports it
main: true, //look for main file
browser: true, //if there is a browser version, use it
}),
commonjs(),
//uglify(),
serve({
contentBase: 'build',
port: '80',
}),
livereload(),
]
Rollup builds it fine. However, in the editor, VSCode displays an error on the d3 symbol. When I hover over it I see this error...
[ts] 'd3' refers to a UMD global, but the current file is a module. Consider adding an import instead.
I can add this import to make the error go away in the editor.
import d3 from '#types/d3';
However, then rollup fails with...
Could not resolve '#types/d3' from '...'
Is there a way to configure vscode to not show that error, so it doesn't drown out real errors?
Is there an alternative way to configure D3 type definitions in a rollup project?
You only have the TypeScript typings for d3 defined. You still need to specify d3 as dependency.
package.json
"dependencies": {
"#types/d3": "4.8.0",
"d3": "4.8.0"
}
You can now import d3:
import * as d3 from "d3";

Resources