Gatsby build ignores few images to copy into static folder - gatsby-image

I have uploads folder with all my assets. When I run gatsby clean / gatsby build, it copies most of the images except 4 of them. It doesn't throw any error or warning as to what it ignores them. The same command on another docker container copies all of the images. The node/gatsby/npm and package.json are precisely the same on both containers. Am I missing something?
Package.json:
{
"name": "gatsby-starter-hello-world",
"private": true,
"description": "A simplified bare-bones starter for Gatsby",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"build": "gatsby build",
"clean": "gatsby clean",
"develop": "gatsby develop -H 0.0.0.0",
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
"start": "npm run develop",
"refresh": "curl -X POST http://localhost:8000/__refresh",
"docker": "docker-compose -f docker-dev.yml up",
"serve": "gatsby serve -H 0.0.0.0 --port 8000",
"db:ql": "node graphql-server.js",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"dependencies": {
"#apollo/react-hooks": "^3.1.2",
"#babel/runtime": "^7.8.4",
"#hot-loader/react-dom": "^16.11.0",
"#use-it/interval": "^0.1.3",
"apollo-boost": "^0.4.7",
"axios": "^0.19.0",
"body-scroll-lock": "^2.6.4",
"bootstrap": "^4.4.1",
"clsx": "^1.0.4",
"cross-env": "^6.0.3",
"final-form": "^4.18.5",
"final-form-calculate": "^1.3.1",
"final-form-set-field-data": "^1.0.2",
"gatsby": "^2.19.10",
"gatsby-image": "^2.2.39",
"gatsby-plugin-alias-imports": "^1.0.5",
"gatsby-plugin-client-side-redirect": "0.0.2",
"gatsby-plugin-lodash": "^3.1.19",
"gatsby-plugin-manifest": "^2.2.40",
"gatsby-plugin-minify-classnames": "^0.1.2",
"gatsby-plugin-offline": "^3.0.33",
"gatsby-plugin-polyfill-io": "^1.1.0",
"gatsby-plugin-react-axe": "^0.3.0",
"gatsby-plugin-react-helmet": "^3.1.21",
"gatsby-plugin-robots-txt": "^1.5.0",
"gatsby-plugin-s3": "^0.3.2",
"gatsby-plugin-sass": "^2.1.27",
"gatsby-plugin-sharp": "^2.4.4",
"gatsby-plugin-sitemap": "^2.2.27",
"gatsby-plugin-webpack-bundle-analyzer": "^1.0.5",
"gatsby-source-filesystem": "^2.1.47",
"gatsby-source-graphql": "^2.5.1",
"gatsby-source-wordpress": "^3.3.1",
"gatsby-transformer-sharp": "^2.3.13",
"gatsby-wordpress-inline-images": "^1.2.1",
"gatsby-wpgraphql-inline-images": "^0.2.5",
"graphql": "^14.6.0",
"graphql-tag": "^2.10.1",
"html-react-parser": "^0.10.0",
"install": "^0.13.0",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.15",
"lodash-es": "^4.17.15",
"moment": "^2.24.0",
"node-sass": "^4.13.0",
"prop-types": "^15.7.2",
"query-string": "^6.8.3",
"react": "^16.12.0",
"react-apollo": "^3.1.2",
"react-autosuggest": "^9.4.3",
"react-bootstrap": "^1.0.0-beta.16",
"react-calendar": "^2.19.2",
"react-datepicker": "^2.11.0",
"react-dates": "^21.8.0",
"react-dom": "^16.12.0",
"react-final-form": "^6.3.5",
"react-helmet": "^5.2.1",
"react-hotjar": "^2.2.0",
"react-icons": "^3.8.0",
"react-image-lightbox": "^5.1.1",
"react-payment-inputs": "^1.0.7",
"react-select": "^3.0.8",
"react-star-ratings": "^2.3.0",
"react-sticky": "^6.0.3",
"styled-components": "^4.4.1"
},
"devDependencies": {
"express": "^4.17.1",
"json-graphql-server": "^2.1.3",
"prettier": "^1.18.2"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-hello-world"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
},
"browserslist": [
"> 2%",
"last 2 versions",
"IE 11"
],
"prettier": {
"tabWidth": 4,
"semi": false
},
"deploy": "gatsby-plugin-s3 deploy --yes"
}
gatsby-config:
/**
* Configure your Gatsby site with this file.
*
* See: https://www.gatsbyjs.org/docs/gatsby-config/
*/
const fs = require('fs')
const path = require("path")
const _ = require("lodash")
const axios = require("axios")
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
const rootPath = path.resolve(__dirname)
// https://gist.github.com/flipace/bed6b89aed5cb0e19cde
function replaceLocalhostBaseUrl(object) {
const newObject = _.clone(object);
_.each(object, (val, key) => {
if (typeof val === 'string' && /(http)(.*)(localhost)(:[0-9]{4})?/.test(val)) {
newObject[key] = val.replace(/(http)(.*)(localhost)(:[0-9]{4})?/, `https://${process.env.WEBSITE_DOMAIN}`)
} else if (typeof val === 'object') {
newObject[key] = replaceLocalhostBaseUrl(val)
} else {
newObject[key] = val
}
});
return newObject;
}
function replaceAbsoluteUrls(contentString){
const regex = /href\s*=\s*(['"])(https?:\/\/.+?)\1/ig
let link
let l
const getLocation = function(href){
let l = document.createElement("a")
l.href = href
return l
}
while((link = regex.exec(contentString)) !== null) {
//only replace urls where localhost or awesomenz.com is mentioned, like uat.awesomenz, dev.awesomenz
if (/localhost|dummy.co.nz/.test(link[2]))
{
l = getLocation(link[2])
contentString = contentString.replace(link[2],
// process.env.SITE_URL +
l.pathname +
"?" +l.href.substring( l.href.indexOf("?")+1 )
);
}
}
return contentString
}
function replaceImagesToLocalEnv(tg){
let fromUrl = "https://uat.dummy.co.nz"
if(process.env.ENV_TYPE == "build")
{
tg.url = tg.url.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.link = tg.link.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.icon = tg.icon.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes.thumbnail = tg.sizes.thumbnail.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes.medium = tg.sizes.medium.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes.medium_large = tg.sizes.medium_large.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes.large = tg.sizes.large.replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes['1536x1536'] = tg.sizes['1536x1536'].replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
tg.sizes['2048x2048'] = tg.sizes['2048x2048'].replace(fromUrl, process.env.MEDIA_BASE_SOURCE_URL)
}
return tg
}
const download_image = async (url, image_path) => {
const imagePathDir = path.dirname(image_path)
await fs.promises.mkdir(imagePathDir, { recursive: true }).catch(console.error);
return axios({
url,
responseType: 'stream',
}).then(
response =>
new Promise((resolve, reject) => {
response.data
.pipe(fs.createWriteStream(image_path))
.on('finish', () => resolve())
.on('error', e => reject(e));
}),
);
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
let wasOgDefaultImageDownloaded = false
let wasOgFrontpageImageDownloaded = false
async function downloadSocialImages(meta) {
if(meta.yoast_wpseo_facebook_image) {
const image = meta.yoast_wpseo_facebook_image
const imageUrl = new URL(image)
await download_image(image, path.join(rootPath, 'public', imageUrl.pathname))
}
if(meta.yoast_wpseo_twitter_image) {
const image = meta.yoast_wpseo_twitter_image
const imageUrl = new URL(image)
await download_image(image, path.join(rootPath, 'public', imageUrl.pathname))
}
if(!wasOgDefaultImageDownloaded && meta.yoast_wpseo_social_defaults.og_default_image) {
wasOgDefaultImageDownloaded = true
const image = meta.yoast_wpseo_social_defaults.og_default_image
const imageUrl = new URL(image)
await download_image(image, path.join(rootPath, 'public', imageUrl.pathname))
}
if(!wasOgFrontpageImageDownloaded && meta.yoast_wpseo_social_defaults.og_frontpage_image) {
wasOgFrontpageImageDownloaded = true
const image = meta.yoast_wpseo_social_defaults.og_frontpage_image
const imageUrl = new URL(image)
await download_image(image, path.join(rootPath, 'public', imageUrl.pathname))
}
}
module.exports = {
siteMetadata: {
title: `dummy`,
// siteUrl is hard coded for use in sitemap.xml (`gatsby-plugin-sitemap`)
siteUrl: process.env.SITE_URL,
},
plugins: [
{
resolve: 'gatsby-plugin-robots-txt',
options: {
host: process.env.SITE_URL,
sitemap: `${process.env.SITE_URL}/sitemap.xml`,
policy: [
{
userAgent: '*',
allow: '/',
disallow: [
'/cart',
'/checkout',
'/filter',
'/filter-tours',
'/manage-booking',
'/mydetails',
'/dev',
'/admin',
'/?flush',
]
},
]
}
},
{
resolve: `gatsby-plugin-polyfill-io`,
options: {
features: [`Array.prototype.find`, 'String.prototype.padStart'],
},
},
`gatsby-plugin-lodash`,
{
resolve: `gatsby-plugin-alias-imports`,
options: {
alias: {
// 'react-dom': '#hot-loader/react-dom',
"entrada-ui": path.join(rootPath, "src/entrada-ui"),
components: path.join(rootPath, "src/components"),
constants: path.join(rootPath, "src/constants"),
queries: path.join(rootPath, "src/queries"),
utils: path.join(rootPath, "src/utils"),
images: path.join(rootPath, "src/images"),
css: path.join(rootPath, "src/css"),
theme: path.join(rootPath, "src/theme"),
},
extensions: [],
},
},
{
resolve: "gatsby-plugin-sass",
options: {
cssLoaderOptions: {
camelCase: true,
},
},
},
{
resolve: `gatsby-plugin-minify-classnames`,
options: {
develop: false, // Enable/Disable on `gatsby develop`
},
},
// {
// resolve: "gatsby-source-graphql",
// options: {
// typeName: "PIH",
// fieldName: "pih",
// url: "https://api.dev.tourcatalogue.co.nz/supplier-graphql-api/query",
// // // HTTP headers
// // headers: {
// // // Learn about environment variables: https://gatsby.dev/env-vars
// // Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
// // },
// // // Additional options to pass to node-fetch
// // fetchOptions: {},
// },
// },
// {
// resolve: "gatsby-source-graphql",
// options: {
// typeName: "WP",
// fieldName: "wp",
// url: "http://localhost:4100/graphql",
// },
// },
// Wordpress
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
// {
// resolve: `gatsby-plugin-manifest`,
// options: {
// name: `gatsby-starter-default`,
// short_name: `starter`,
// start_url: `/`,
// background_color: `#663399`,
// theme_color: `#663399`,
// display: `minimal-ui`,
// icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
// crossOrigin: `use-credentials`,
// },
// },
{
resolve: "gatsby-source-wordpress",
options: {
baseUrl: `${process.env.WORDPRESS_URL}`,
protocol: `${process.env.WP_PROTOCOL}`,
plugins: [
{
resolve: `gatsby-wordpress-inline-images`,
options: {
baseUrl: `${process.env.WORDPRESS_URL}`,
protocol: `${process.env.WP_PROTOCOL}`
// baseUrl: `uat.dummy.co.nz`,
// protocol: `https`
}
}
],
// TODO: Need to have further testing
// searchAndReplaceContentUrls: {
// sourceUrl: `${process.env.SITE_URL}`,
// replacementUrl: "",
// },
hostingWPCOM: false,
useACF: true,
acfOptionPageIds: [],
verboseOutput: false,
perPage: 100,
// Set how many simultaneous requests are sent at once.
concurrentRequests: 10,
includedRoutes: [
"**/categories",
"**/posts",
"**/pages",
"**/media",
"**/tags",
"**/tours",
"**/destinations",
"**/themes",
"**/taxonomies",
"**/announcements",
"**/*/*/menus", // <== Menu api endpoint
"**/*/*/menu-locations", // <== Menu api endpoint
"**/exposeredirections", // <== Exposeredirections api endpoint
],
excludedRoutes: [],
normalizers: normalizers => {
return _.compact([
process.env.MEDIA_BASE_SOURCE_URL ?
{
name: `changeMediaSourceUrls`,
normalizer: async ({
entities,
}) => (
entities.map((entity) => {
if(entity.content && entity.content !== ""){
entity.content = replaceAbsoluteUrls(entity.content)
}
///////////////////////////////////////////////////////////
if(entity.acf)
{
if(entity.acf.gallery)
{
let nLoop = entity.acf.gallery.length
if( nLoop > 0)
{
let tempGallery = []
for(let c=0; c<nLoop; c++){
tempGallery.push( replaceImagesToLocalEnv(entity.acf.gallery[c]) )
}
entity.acf.gallery = tempGallery
}
}
if(entity.acf.card_image)
{
entity.acf.card_image = replaceImagesToLocalEnv(entity.acf.card_image)
}
if(entity.acf.card_map)
{
entity.acf.card_map = replaceImagesToLocalEnv(entity.acf.card_map)
}
if(entity.acf.image)
{
entity.acf.image = replaceImagesToLocalEnv(entity.acf.image)
}
if(entity.acf.info_cards)
{
let nLoop = entity.acf.info_cards.length
if( nLoop > 0)
{
let tempCardsInfo = []
let tmp
for(let c=0; c<nLoop; c++){
tmp = entity.acf.info_cards[c]
tmp.card_image = replaceImagesToLocalEnv(tmp.card_image)
tempCardsInfo.push( tmp )
}
entity.acf.info_cards = tempCardsInfo
}
}
}
///////////////////////////////////////////////////////////
if(entity.__type === 'wordpress__wp_media') {
// Transforms:
// https://uat.dummy.co.nz/wp-content/uploads/2020/01/Placeholder-Image.png
// into:
// http://localhost/wp-content/uploads/2020/01/Placeholder-Image.png
entity.source_url = `${process.env.MEDIA_BASE_SOURCE_URL}/${entity.source_url.split("/").slice(3).join('/')}`
} else if (entity.yoast_meta) {
downloadSocialImages(entity.yoast_meta)
entity.yoast_meta.yoast_schema = typeof entity.yoast_meta.yoast_schema === 'string' ? JSON.parse(entity.yoast_meta.yoast_schema) : entity.yoast_meta.yoast_schema
entity.yoast_meta = replaceLocalhostBaseUrl(entity.yoast_meta)
entity.yoast_meta.yoast_schema = JSON.stringify(entity.yoast_meta.yoast_schema)
}
return entity
})
)
} : undefined,
...normalizers
])
},
},
},
// {
// resolve: 'gatsby-wpgraphql-inline-images',
// options: {
// wordPressUrl: process.env.MEDIA_BASE_SOURCE_URL+'/',
// uploadsUrl: process.env.MEDIA_BASE_SOURCE_URL+'/wp-content/uploads/',
// processPostTypes: ['Page', 'Post', 'CustomPost'],
// graphqlTypeName: 'WPGraphQL',
// httpHeaders: {
// Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
// }
// },
// },
{
resolve: `gatsby-plugin-s3`,
options: {
bucketName: 'static-dummy'
},
},
{
resolve: `gatsby-plugin-sitemap`,
options: {
// See: https://github.com/isaacs/minimatch
// The example below will exclude the single `path/to/page` and all routes beginning with `category`
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage {
edges {
node {
path
}
}
}
}`,
serialize: ({ site, allSitePage }) =>
allSitePage.edges.map(edge => {
return {
url: site.siteMetadata.siteUrl + edge.node.path,
changefreq: `daily`,
priority: 0.7,
}
})
}
},
`gatsby-plugin-client-side-redirect`, // keep it in last in list,
// {
// resolve: 'gatsby-plugin-react-axe',
// options: {
// // Integrate react-axe in production. This defaults to false.
// showInProduction: false,
// },
// },
// {
// resolve: 'gatsby-plugin-webpack-bundle-analyzer',
// options: {
// analyzerPort: 8888,
// production: true,
// },
// }
],
}
env file:
# If you are running `npm run build` in your local, you need to add the port :8080
# to WORDPRESS_URL and MEDIA_BASE_SOURCE_URL
WORDPRESS_URL=localhost
MEDIA_BASE_SOURCE_URL=http://localhost
WP_POD_PUBLIC_URL=https://uat.dummy.co.nz
WP_PROTOCOL=http
ENV_TYPE=build
WEBSITE_DOMAIN=uat.dummy.co.nz
SITE_URL=https://www.uat.dummy.co.nz
GATSBY_CPU_COUNT=logical_cores

Related

Electron js Electron builder mac built opening blank white screen when run , while works perfectly in development when run using npm start

I have created built in both windows and ubuntu,the app runs properly. But when build in mac, the build is created successfully but it shows just white blank screen no html page rendered. while when run using npm start it runs perfectly. I have problem only with mac build
below is the package.json
{
"name": "collab",
"version": "1.0.0",
"description": "",
"main": "app.js",
"homepage": "someurl",
"scripts": {
"start": "electron .",
"dist:linux": "electron-builder --linux",
"dist:windows": "electron-builder --windows",
"dist:mac": "electron-builder -m",
"postinstall": "electron-builder install-app-deps",
"package": "electron-packager . --production"
},
"author": "",
"license": "ISC",
"dependencies": {
"#slack/web-api": "^6.7.2",
"auto-launch": "^5.0.5",
"axios": "^0.27.2",
"base64-img": "^1.0.4",
"dotenv": "^16.0.1",
"electron-log": "^4.4.8",
"ext-ip": "^0.3.9",
"geoip-lite": "^1.4.5",
"geolib": "^3.3.3",
"moment": "^2.29.3",
"mongoose": "^5.13.2",
"open": "^8.4.0",
"screenshot-desktop": "^1.12.3",
"socket.io-client": "^3.0.4",
"sqlite3": "^5.1.2"
},
"devDependencies": {
"#types/node": "^18.0.0",
"electron": "^11.1.0",
"electron-rebuild": "^3.2.9"
},
"build": {
"appId": "collab",
"linux": {
"target": [
"deb"
],
"icon": "build/icons/icon_256x256.png",
"category": "Utility"
},
"mac": {
"target": "dmg",
"icon": "build/icons/icon_512x512.png"
},
}
}
Few functions that I use in app.js
app.whenReady().then(() => {
connectivityCheck();
});
function connectivityCheck() {
connectivityInterval = setInterval(function () {
dns.resolve("www.google.com", function (err, addr) {
if (err) {
let reminder = new Notification({
title: 'Collab:Error',
body: 'No internet connectivity found'
});
reminder.show();
} else {
let reminder = new Notification({
title: 'Collab',
body: 'Internet connection found'
});
reminder.show();
connectivityStatus = true;
appReadyProcess();
}
});
}, 10000);
}
function appReadyProcess() {
setUpWindow().then(() => {
askPermission().then(() => {
if (connectivityStatus) {
clearInterval(connectivityInterval);
manageDBConnection();
}
});
});
}
function manageDBConnection() {
connectDB(process.env.MONGO_URI).then(() => {
socket.emit("join-message", "hello");
open(process.env.SERVER_URL + "/setLocation");
loginScreen();
verifyUserTimer();
}).catch((err) => {
appLogs.error(err);
});
}
Few functions that i use in method.js file
function setUpWindow() {
return new Promise((resolve, reject) => {
if (BrowserWindow.getAllWindows().length === 0) {
window_app = new BrowserWindow({
width: 500,
height: 660,
resizable: false,
webPreferences: {
nodeIntegration: true,
},
});
window_app.removeMenu();
//window_app.webContents.openDevTools(); // Opening inspect elements
window_app.tray = new Tray(nativeImage.createEmpty());
const menu = Menu.buildFromTemplate([
{
label: "Actions", submenu: [
{
label: "Open Collab", click: (item, window, event) => {
window_app.show();
}
},
]
},
{ type: "separator" },
{
label: 'Quit', click: function () {
window_app.removeAllListeners('close');
window_app.close();
app.quit();
}
}
]);
window_app.tray.setContextMenu(menu);
window_app.icons = new BrowserWindow({
show: false, webPreferences: { offscreen: true }
});
window_app.icons.loadURL("https://trends.google.com/trends/hottrends/visualize");
window_app.icons.webContents.on("paint", (event, dirty, image) => {
if (window_app.tray) window_app.tray.setImage(image.resize({ width: 16, height: 16 }));
});
window_app.on('close', (event) => {
if (app.quitting) {
window_app = null
} else {
event.preventDefault()
window_app.hide()
}
});
resolve(true);
}
}).catch((err) => {
logs.error(err);
});
}
function askPermission() {
return new Promise((resolve, reject) => {
if (process.platform === 'darwin' || process.platform === 'win32') {
systemPreferences.getMediaAccessStatus('screen');
resolve(true);
} else {
resolve(true);
}
}).catch((err) => {
logs.error(err);
});
}
function loginScreen() {
let login = false;
new Promise((resolve, reject) => {
db = new DBFuntions();
query = "select * from user_data";
db.getDetails(query).then((data) => {
if (data.length === 0) { // || (Number(data[0].expire_token_date) < currentTs)
login = true;
}
let filename;
if (login) {
filename = `file://${__dirname}/login.html`;
window_app.loadURL(filename);
} else {
getUserByEmail(data[0].email).then((DBUser) => {
userDetails = DBUser;
});
filename = `file://${__dirname}/index.html`;
window_app.loadURL(filename);
}
resolve(true);
});
}).catch((err) => {
logs.error(err);
});
}
even app icon and tray icon are properly shown when app open.
It works fine for windows and ubuntu only problem with mac built. while it runs properly in local/development for mac when run using npm start app.js
I was able to solve the issue with the use of logs by using
const appLogs=require('electron-log');
appLogs.transports.console.level = false;
I was able to get the required details from the logs that helped me to solve the issue.The exception or error was generated by something else.

Apollo client's offsetLimitPagination requests for graphql server although the data is available in cache

Whenever I navigate to different pages, data will be added to Apollo's cache. but when I navigate to previous pages, although the data is available in cache. Apollo issues a network request to graphql server.
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: {
...offsetLimitPagination(),
read(existing, { args }) {
return (
existing &&
existing.slice(
args?.offset,
args?.offset + args?.limit
)
)
},
}
},
},
},
})
const client = new ApolloClient({
uri: "https://api.spacex.land/graphql/",
cache,
connectToDevTools: true,
})
And my component:
const Users: React.FC = () => {
const [offset, setOffset] = useState(0)
const { loading, data, error, fetchMore } = useUsersQuery({ \\ Generated via graphql-code-gen
variables: { offset, limit: 2 },
})
const fetchMoreHandler = (): void => {
const currentLength = data?.users.length || 0
fetchMore({
variables: { offset: offset + currentLength, limit: 2 },
}).then(() => {
setOffset((ofsset) => ofsset + currentLength)
})
}
const fetchPrevHandler = (): void => {
let currentLength = data?.users.length || 0
if (currentLength === 0) {
currentLength = 2
}
fetchMore({
variables: { offset: offset - currentLength, limit: 2 },
}).then(() => {
setOffset((ofsset) => ofsset - currentLength)
})
}
if (loading) {
return <div>Loading....</div>
}
if (error) {
return <div>Something went wrong!</div>
}
return (
<div className={classes.root}>
{offset > 0 && (
<button type="button" onClick={fetchPrevHandler}>
Prev
</button>
)}
<div>
{data?.users.map((user) => (
<div key={user.id}>
<h6>{user.name}</h6>
</div>
))}
</div>
{(data?.users.length || 0) > 0 && (
<button type="button" onClick={fetchMoreHandler}>
Next
</button>
)}
</div>
)
}
export default Users
And here's the query:
query Users($offset: Int, $limit: Int) {
users(offset:$offset, limit: $limit, order_by:[{timestamp:desc}]) {
id
name
rocket
timestamp
twitter
}
}
When I navigate my cache looks like this:
_APOLLO_CLIENT_.cache.data.data:
{
"users:a75bf714-30e4-4219-8335-e413f8f127ef": {
"id": "a75bf714-30e4-4219-8335-e413f8f127ef",
"__typename": "users",
"name": "HI",
"rocket": "FRIENDS",
"timestamp": "2021-12-22T18:38:09.805832+00:00",
"twitter": null
},
"users:c2317843-8481-4cb6-87e1-16d8f4aa7092": {
"id": "c2317843-8481-4cb6-87e1-16d8f4aa7092",
"__typename": "users",
"name": "simeooone",
"rocket": "tha_rocket",
"timestamp": "2021-12-22T16:14:50.431972+00:00",
"twitter": "#galfh"
},
"ROOT_QUERY": {
"__typename": "Query",
"users": [
{
"__ref": "users:a75bf714-30e4-4219-8335-e413f8f127ef"
},
{
"__ref": "users:c2317843-8481-4cb6-87e1-16d8f4aa7092"
},
{
"__ref": "users:f6358c49-7ce3-491e-8103-48e9e4b847cd"
},
{
"__ref": "users:a04c9b78-3406-4585-ba16-0a4c540fdc23"
}
]
},
"users:f6358c49-7ce3-491e-8103-48e9e4b847cd": {
"id": "f6358c49-7ce3-491e-8103-48e9e4b847cd",
"__typename": "users",
"name": "aemilio",
"rocket": "yo_mum",
"timestamp": "2021-12-22T16:11:14.728876+00:00",
"twitter": "#yo_mum"
},
"users:a04c9b78-3406-4585-ba16-0a4c540fdc23": {
"id": "a04c9b78-3406-4585-ba16-0a4c540fdc23",
"__typename": "users",
"name": "",
"rocket": "oy",
"timestamp": "2021-12-22T16:10:24.420815+00:00",
"twitter": "asd"
}
}
And when I navigate back to show these exact items, still apollo makes network requests!
For other's that are new to Apollo like me and have this question, I figured out that fetchMore function always force network request no matter what. That's by design. If you want to read from cache you shouldn't use fetchMore and do something like this instead:
const [offset, setOffset] = useState(0)
const { loading, data, error } = useUsersQuery({
variables: { offset, limit: 2 },
})
const fetchMoreHandler = (): void => {
const currentLength = data?.users.length || 0
setOffset((ofsset) => ofsset + currentLength)
}
const fetchPrevHandler = (): void => {
let currentLength = data?.users.length || 0
if (currentLength === 0) {
currentLength = 2
}
setOffset((ofsset) =>
ofsset - currentLength < 0 ? 0 : ofsset - currentLength
)
}
and this would be your instance of InMemoryCache:
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: {
...offsetLimitPagination(),
read(existing, { args }) {
let res
if (existing) {
res = existing.slice(
args?.offset,
args?.offset + args?.limit
)
}
return res && res.length === args?.limit
? res
: undefined
},
},
},
},
},
})

How to watch and set dynamically a variable?

Hi it's my first post on StackOverflow.
I'm working on for translating dynamically a website. I'm using the package vuejs-localization.
How can I switch language directly?
I'm working with the latest version of VueJS and Laravel.
This is my code on my language selector:
export default {
name: "LanguageDropDown",
data() {
return {
languages: [
{
lang: "fr",
text: "Français",
icon: "fr",
},
{
lang: "gb",
text: "English",
icon: "gb",
},
{
lang: "us",
text: "US",
icon: "us"
},
],
};
},
computed: {
getCurrentLang: function() {
return this.$lang.getLang();
},
},
methods: {
setLanguage(lang) {
this.$root.$emit("setLang", lang);
},
setLang(lang, index) {
this.$root.$emit("setLang", this.languages[index].languages[lang], index);
},
},
};
And this is what is in my App.js :
const app = new Vue({
el: '#app',
router,
data() {
return {
lang: 'fr'
};
},
created() {
this.$lang.setLang( this.lang );
},
mounted() {
let _this = this;
this.$root.$on( 'setLang', function( lang ){
_this.lang = lang ;
console.log(_this.lang);
});
},
watch: {
lang :{
handler(val){
this.lang = val;
console.log('changed to :' + this.lang);
},
},
},
})
I expect a translation by changing the variable 'fr' to 'us' or 'gb' but the log says that the lang is switching but nothing happened ...
Thanks for your help.
To make language changes, you need to call this.$lang.setLang. You can do it in watch
watch: {
lang :{
handler(val){
this.lang = val;
this.$lang.setLang(val)
console.log('changed to :' + this.lang);
},
},
},

d3 and webpack: __WEBPACK_IMPORTED_MODULE_0_d3__.scaleLinear is not a function

I'm attempting to use d3 to render some graphs in my Vuejs components. I am importing d3 as recommended import * as d3 from 'd3' and attempting to call d3 functions on it.
webpack.base.conf.js
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src'),
'src': resolve('src'),
'components': resolve('src/components'),
'assets': resolve('src/assets'),
'static': resolve('static'),
'styles': resolve('src/styles')
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
.babelrc
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": [
"dynamic-import-node",
"syntax-dynamic-import",
"transform-runtime"
],
"env": {
"test": {
"presets": [
[ "env", { "targets": { "node": 8}}],
],
"plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
Error from the console: Vue warn]: Error in mounted hook: "TypeError: __WEBPACK_IMPORTED_MODULE_0_d3__.scaleLinear is not a function"
Component using d3:
import * as d3 from 'd3'
const graphW = '200'
const graphH = '30'
const xDomain = [1, 10]
const xRange = [0, 200]
const yRange = [30, 0]
export default {
...
methods: {
render: function () {
var self = this
var graph = d3.select('.' + self.className).append('svg:svg').attr('width', graphW).attr('height', graphH)
var data = self.data
var x = d3.scaleLinear().domain(xDomain).range(xRange)
var y = d3.scaleLinear().domain([d3.min(data), d3.max(data)]).range(yRange)
...
Try
.scale.linear()
instead of .scaleLinear()
I think it is different on npm version.
I had a similar error when using some D3 example with D3 v5:
[Vue warn]: Error in mounted hook: "TypeError:
WEBPACK_IMPORTED_MODULE_0_d3.schemeCategory10 is not a function"
I solved it by removing parentheses from scaleLinear, changing:
var x = d3.scaleLinear().domain(xDomain).range(xRange)
var y = d3.scaleLinear().domain([d3.min(data), d3.max(data)]).range(yRange)
to:
var x = d3.scaleLinear.domain(xDomain).range(xRange)
var y = d3.scaleLinear.domain([d3.min(data), d3.max(data)]).range(yRange)

Graphql Cannot create property 'clientMutationId' error on mutation?

this is the mutation I want to perform:
const GraphQLAddPlayerResponseMutation = mutationWithClientMutationId({
name: 'AddPlayerResponse',
inputFields: {
cdx: { type: new GraphQLNonNull(GraphQLInt) },
},
mutateAndGetPayload: ({cdx}) => {
var cdxAdded = addplayerResponse(cdx);
console.log("cdxAdded = ",cdxAdded)
return cdxAdded;
}, // what u return on mutateAndGetPayload is available on outputFields
outputFields: {
playerResponse: {
type: GraphQLInt,
resolve: ({cdxAdded}) => {
console.log("outputFields cdxAdded = ",cdxAdded)
return cdxAdded
},
},
viewer: {
type: GraphQLUser,
resolve: () => getViewer(),
},
},
});
Can't figure out what's wrong with the code, it logs on the mutateAndPayload:
mutateAndGetPayload: ({cdx}) => {
var cdxAdded = addplayerResponse(cdx);
console.log("cdxAdded = ",cdxAdded)
return cdxAdded;
},
but I think the outputFields is not evaluated since it's not logging in the console and I get this error:
{
"data": {
"addPlayerResponse": null
},
"errors": [
{
"message": "Cannot create property 'clientMutationId' on number '3'",
"locations": [
{
"line": 4,
"column": 3
}
],
"path": [
"addPlayerResponse"
]
}
]
}
Help?
Replace return cdxAdded; by return { cdxAdded }; (wild guess)

Resources