How can I ensure this vue application doesn't exceed the recommended 244kb in production? - vue.js

There is a vue file here that imports a json file that has about 9000 records in it.
How do I ensure that the json file is not compiled with the component?

A simple way would be to put the JSON file you want to access in the public folder (Webpack won't process anything in this folder). Then use AJAX to call the file at run time.
This will avoid expanding your app bundle, but Vue may still show that you're including a large resource. This approach would also allow you to split the data into smaller chunks and load them as needed in your app.
Here's an example, assuming the data file is located at /public/data/mydata.json. Also, I suggest using Axios to make the AJAX stuff easier.
import axios from 'axios'
export default {
name: 'Vue Component',
created() {
this.fetchData();
},
methods: {
fetchData() {
axios.get('/data/mydata.json').then(response => {
// do something with response.data
})
}
}
}

Use dynamic import. Like this:
import(
/* webpackChunkName: "my_json" */
'./src/my.json'
).then(({default: myJson}) => {
// do whatever you like here~
console.log(myJson);
});
doc:
https://webpack.js.org/guides/code-splitting/#dynamic-imports
If the json file is too big, you will still get the size exceeding warning.
But the json file would load async, so it would not cause any performance problem.
🔽 🔽 🔽 if you really don't want to see the warning, try this: 🔽 🔽 🔽
Use copy-webpack-plugin,it can copy your json file to dist folder, which means you can fire a XHR get request to load the json file, like this axios.get('/my.json').
By doing this, you can get the FULL control about when to load the file.

Related

Fetch data from local JSON file with Nuxt Pinia

Is it possible to fetch a local .json. file using fetch()? I originally used the import method but the site's data doesn't get updated unless the page gets reloaded.
I tried doing this but it's not working:
stores/characters.ts
export const useCharactersStore = defineStore("characters", {
state: () => ({
characters: [],
}),
getters: {
getCharacters: (state) => {
return state.characters;
},
},
actions: {
fetchCharacters() {
fetch("../data.json")
.then((response) => response.json())
.then((data) => {
this.characters = data.characters;
});
},
},
});
app.vue
import { useCharactersStore } from "~/stores/characters";
const store = useCharactersStore();
onMounted(() => {
store.fetchCharacters();
});
Any help would be appreciated.
maybe a bit late but I have encountered the same problem migration from Nuxt 2 to Nuxt 3.
I'm certainly no expert on this, so if anyone finds a better way or if I'm totally wrong please let me know !
Whenever you import a json file in vue code they are imported as a module, that get's embedded within the code compilation on build (Vue Docs). Tu use json as a external file you need to place your json within the /public directory and use axios or fetch to load the file with a lifecyle hook.
This could be mounted() for options api or beforeMount()/onMounted() with composition api.
However some important annotations for this method.
If the json file you want to use in your app is not reactive, i.e. won't change, you should place this in the static folder of the nuxt app.
In your example you fetch '../data/...', this would imply the server knows the domain to look for. It can't call the route like this, you would have to give the full url if you put your json file in the static folder.
Set the baseUrl in the of your nuxt.config.ts, see docs for specifications.
Then you can access the static folder with your .env variables
--> $fe
Then in you data script you can access your json file
async getJson(some parameters){
const data = $fetch('your domain with the runtimeConfig composable').then((data)=>{ console.log(data)});
Sidenote you can also load the file from the server-side using fs.readFile
read more about this in this awesome post here

React-native: download and unzip large language file

A multilingual react-native app. Each language bundle is ~50MB. It doesn't make sense to include all of them in a bundle. So, what do I do about it?
I assume the right way to go here is to download the respective language files upon language selection.
What do I do with it next? Do I suppose to store it using AsyncStorage or what?
Briefly explaining, you will:
Store JSON as ZIP in Google Storage (save memory/bandwidth/time)
Unzip file to JSON (in RN)
Store JSON in AsyncStorage (in RN)
Retrieve from AsyncStorage (in RN)
[Dependencies Summary] You can do this, using these deps:
react-native
react-native-async-storage
rn-fetch-blob
react-native-zip-archive
Tip: Always store big language json in zip format (this can save up to 90% of size).
I made a quick test here: one 3.52MB json file, turned out a 26KB zipped file!
Let's consider that yours stored zip file, can be accessed by using a public url, eg: https://storage.googleapis.com/bucket/folder/lang-file.zip.
Install and link all above RN deps, it's required to get this working.
Import the deps
import RNFetchBlob from 'rn-fetch-blob';
import { unzip } from 'react-native-zip-archive';
import AsyncStorage from '#react-native-community/async-storage';
Download the file using rn-fetch-blob. This can be done using:
RNFetchBlob
.config({
// add this option that makes response data to be stored as a file,
// this is much more performant.
fileCache : true,
})
.fetch('GET', 'http://www.example.com/file/example.zip', {
//some headers ..
})
.then((res) => {
// the temp file path
console.log('The file saved to ', res.path())
// Unzip will be called here!
unzipDownloadFile(res.path(), (jsonFilePath) => {
// Let's store this json.
storeJSONtoAsyncStorage(jsonFilePath);
// Done!
// Now you can read the AsyncStorage everytime you need (using function bellow).
});
});
[function] Unzip the downloaded file, using react-native-zip-archive:
function unzipDownloadFile(target, cb) {
const targetPath = target;
const sourcePath = `${target}.json`;
const charset = 'UTF-8';
unzip(sourcePath, targetPath, charset)
.then((path) => {
console.log(`unzip completed at ${path}`)
return cb(path);
})
.catch((error) => {
console.error(error)
});
}
[function] Store JSON in AsyncStorage:
function storeJSONtoAsyncStorage (path) {
RNFetchBlob.fs.readFile(path, 'utf-8')
.then((data) => {
AsyncStorage.setItem('myJSON', data);
});
}
Retrieve JSON data from AsyncStorage (everytime you want):
AsyncStorage.getItem('myJSON', (err, json) => {
if (err) {
console.log(err);
} else {
const myJSON = JSON.parse(json);
// ... do what you need with you json lang file here...
}
})
That's enough to get dynamic json lang files working in React Native.
I'm using this approach to give a similar feature to my i18n'ed project.
Yes you are right to make the translation file downloadable.
You can store the downloaded file in the document directory of your app.
After that you can use a package to load the translations. For instance
https://github.com/fnando/i18n-js.
I would also suggest taking a look at the i18n library which is a standard tool for internationalisation in JavaScript.
Consider taking a look at this documentations page where you can find an option of loading a translation bundle or setting up a backend provider and hooking into it.
Also, to answer the storage question, if you do not plan on setting up a backend: AsyncStorage would be an appropriate place to store your key - translation text pairs.

How can I load JSON config file and let the Vue app wait for this?

A typical scenario for me is:
a Vue app (packed with webpack, BTW)
a separate config file for configuring the app
The config file should not be included in the webpacked deployment package, since it is server-dependent (database credentials etc.)
For some reason I am not intending to elaborate on here I keep the config in a JSON file.
So the question is:
How can I delay "starting" the Vue app until the JSON config file has been loaded (and parsed) from the backend?
I know how to load and parse, but the question for me is Vue-specific: what's the best practice to "wait" for something before starting the whole thing?
(Is something like beforeCreate lifecycle hook in the App.vue component the way to go? Does it play nice with asynchronous tasks like loading a JSON file over the net?)
One way that I have used to solve this kind of issue is to use the router.beforeEach. Here is an example of my code:
router.beforeEach(async (to, from, next) => {
if (!store.state.initialized) {
// the store initialize will set initialized to true
await store.dispatch('initialize')
}
// if user not logged in or the route is not public
if (!store.state.user && !to.meta.public) {
next('/login')
} else {
next();
}
});

Prevent JSON file from becoming part of chunk.js/app.js when I build my vue app

I have a JSON file that I included in my vue app. But the problem is that when I build the app, the JSON file disappears and becomes a part from a js file.
How can I keep it as a JSON file after build, since I want to manipulate it?
If you are using Vue CLI 3, you can place your static files in public directory and reference them by absolute paths.
For more information you can visit the CLI documents.
Update
Place your JSON file in public directory
Import axios or any similar tools you use for AJAX calls.
You need a .env file in your project root. And store your base url in BASE_URL variable. (Read More!)
Add a data property containing your base URL:
data() {
return {
baseUrl: process.env.BASE_URL,
}
},
And then you can access you JSON value with an ajax call:
axios.get(this.baseUrl + 'test.json').then(response => {
console.log(response);
})
I think you want to configure the externals option.

Load AJAX in Framework7, vue

I'm very new to Framework7, and want to build a fairly simple mobile app -- a list of places, detail pages of those places (where some murals are displayed), and a map and about page. My current plan is to publish it via PhoneGap Build, since that seems like a fast and easy way to deploy.
I created my app using the phonegap-framework7-vue template. Perhaps overkill for such a simple app, but seems better than building it from scratch.
I want to load a list of places via AJAX (eventually via sqlite), and can't figure out how/when to do this, and how to access the main app. My Murals.vue file has the template and the following script, but doesn't load because app.request is undefined. I've tried "framework7", "Framework7", and moving it outside of the mounted() call, but feel like I'm just guessing. Any suggested? Thanks!
<script>
import F7List from "framework7-vue/src/components/list";
let dataURL = 'https://jsonplaceholder.typicode.com/posts'; // returns some json
export default {
name: 'Murals',
components: {F7List},
mounted() { // when the Vue app is booted up, this is run automatically.
app.request.get(dataURL, function (data) {
console.log(data);
});
},
data () {
return {
title: 'Murals'
};
}
};
</script>
You're code is almost right !
To access to F7 app instance with vue, you have to use this.$f7.request rather the app.request