Vue load a JS file with a javascript object in a runtime - javascript

I am building a no-code application using Vue. I have an idea that I have some JSON file and import it on runtime. However, JSON file don't allow to add a function. I change to use a javascript or typescript file to store the JSON object like below.
export {
"is": "button",
"props": {
"type": "button"
},
"events": {
"click": () => {
// do something
}
}
}
Currently, I want to trigger the import when Vue created the component.
{
created () {
// import here
}
}
I have two methods that I have tried:
Add a script tag but I need something to store it first, like window
use import but it only supports local file.
I store these files in backend and load each of them when frontend need it. Is there any better solution? Please help and thank you.

It sounds like you essentially want to do something like deferred module loading, if you use Webpack you may want to have a look at this: https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/
I'm not sure I can recommend the approach that you're taking but if you do want to stick with it, your solution would probably look something like:
Make an HTTP get request to the URL of your file. This should be a plain text response, not JSON. The file itself can be a .js file containing an object literal ({ a: ..., b: ..., c: ... }) with function definitions.
Once you get the text, evaluate it with eval(...the response) and save it to a local variable which you can then use. Note that if the code in your file has any dependencies, you will have to come up with some way to bring those over as well.
Clearly though, this is a lot of trouble and probably not worth it. Code splitting in general is only worth the effort if it's a fairly big app; for smaller apps the cost of the round trips outweighs the cost of loading the initial bundle.
In any case, you'll likely have more luck using Vue's baked-in dynamic import system than a hand-rolled solution, but it really just depends on what you're trying to achieve here.

Related

How to import data from one svelte file to another

Sorry if I'm doing something wrong, I'm just starting with Svelte. I looked around on the web and couldn't find anything
I have a large hard coded data array made of objects that I want to keep in its own file while being able to access the data in app.svelte. I'm trying to keep my app.svelte as simple as possible. I tried export const data=[{data:"mydata"}] along with import {data} from "./data.svelte" but the export keyword means it expects the data to be sent over to data.svelte file, not the other way around. I really have no clue how to acheive this in Svelte. The data could also be json in a json file, as long as it is imported in my app.
Thank you for your help
.svelte files should be reserverd for components only, you can add your data in a regular javascript file instead
in data.js
export const data=[{data:"mydata"}]
in App.svelte
<script>
import { data } from './data.js'
</script>
This is possible with json files as well, but it will require an extra step as svelte does not by default understand json files. Depending on what bundler you use, you will have to add plugin, for Rollup this is https://www.npmjs.com/package/#rollup/plugin-json

Best practice for splitting up a large object of data for lighter importing

I produce a large json file that contains an object with multiple config properties. I plan on distributing it as a resource but i want to do it in the most size efficient way possible. The way it works now is the file that needs a config property imports the whole json file, and accesses it as configs.config1.
Please note that I am distributing this as a lib. One person suggested that I don't have to change the way I split the object because the user can just do clever things with webpack. I cannot enforce that so I would like to handle this from the lib side.
These are the two ways i figured may make the most sense:
Split each configX into its own file
(i.e. import config from 'config1.json';)
Use a js file with multiple exports instead of a json file
(i.e. import { config1 } from 'configs')
I'm not sure which would be the most size efficient for the users to import. I need to add the least amount of weight to people's projects as possible. If there's an even better option I'm not considering, please let me know!
JSON
{
config1: {...},
config2: {...},
config3: {...},
...
}
My current docs usage instruction:
import configs from 'configs.json';
var myConfig = configs.config1

A clean way to allow React shared component to get configuraiton property without having to pass it all the way down

I have about 8 simple UI's for different applications, all of them make use of a shared components library I also produce. I recently added a feature to modify how querying is done in the low levels of a some utility functions used in all the saga of all my UIs.
I want each of my UIs to be able to include an optional configuration value to tweak this new querying logic in their configuration files. However, the method that needs the property is very low level, I'd prefer not to have to add an extra property to 5-6 methods to pass one value down to the method that needs it.
These shared components are used only for my UI, which all have a standard format. As such I don't need them to be fully generic, I have no complaint with hard coding their checking the standard location of my configuration file in my UIs. However, since the shared components are a separate NPM package I don't know how to reference the location of a configuration file in the applications calling the UI.
Is there any clean way to get the value from the configuration file other then just passing it through all the relevant methods?
It's simple. You can create configuration file where you'll export your logic. And when you need that config, import that and use. Here's an example:
configuration.js
export const test = (myvar) => {
return 'test: ' + myvar
}
component.js
import { test } from 'configuration.js'
test('pass') // test: passed

Execute NormalModule at build time, after it is built by loaders, then save to json file

I am coding a plugin that, for specific modules, will try to execute the module generated at build time in order to save the result to a json file.
For that, I am tapping into compilation.hooks.succeedModule, which receives a NormalModule object already built. Then I am trying to eval the source replacing webpack variables like __webpack_public_path__.
While it kind of works, this approach feels terribly wrong. Like I am missing something.
Is there a nice way to execute modules at build time from a NormalModule object having basic access to vars like __webpack_public_path__? Maybe Webpack offers a better way to do these kind of things?
Ok, yeah, sounds like you can solve this another way, I've done similar stuff where I needed to change what a module output, write stuff to disk, trigger side effects, etc. It sounds like you want loaders rather than a plugin. The run-loader (https://www.npmjs.com/package/webpack-run-loader) executes the module it loads and exports or returns the result.
You can write a custom loader that you chain to run after responsive-loader, and run-loader, and which receives the JSON from run-loader and writes it to disk where you want it (as a side effect), and then returns an empty string so that nothing is added to the build. The end result would be that requiring this module in your app gets your image files created (by responsive-loader), and the JSON written out to disk where you need it (by your custom loader). Alternately you could skip run-loader and in your custom loader use regex to just grab the JSON from the output of responsive-loader. Using regex on code generated by a project dependency seems fragile, but as long as you have your dependency versions locked down it can work just fine in practice, and it's a bit simpler conceptually than adding run-loader to the pipeline.
If you're writing webpack plugins I imagine you're comfortable writing loaders as well, but if not they're pretty straightforward -- just a function that accepts source code from the loader that came before it and returns code, and does whatever you want in between. The docs aren't bad for the API, but looking at the source of a few published loaders is helpful, too. It might look roughly (just spitballing from memory) like:
// img-info-logging-loader.js
// regex version, expects source arg to be output of responsive-loader
import * as fs from 'fs';
export const imgInfoLoggingLoader = (source) => {
const jsonFinderRegex = /someregexto(match)onsource/;
const desiredJSON = source;
const matchArr = jsonFinderRegex.exec(desiredJSON);
if (!matchArr[1]) {
throw new ReferenceError('json output not found in loader source.');
} else {
const imgConfigJsonString = matchArr[1];
// you would write a fn to generate a filename based on the
// source, or based on the module's filename, which is available
// via the webpack loader api
const fileNameToWrite = getFileNameTowrite();
try {
// async might be preferable depending on your webpack
// performance needs
fs.writeFileSync(fileNameToWrite, imgConfigJsonString);
} catch (err) {
throw new Error(`error writing ${fileNameToWrite}`);
}
}
// what the loader inserts into your JS asset: empty string
return '';
}
EDIT:
Since per your comment you are looking to output a single JSON object with all of the image info in it, you would want a slightly different approach that does use a plugin (this is the most elegant way I know to do it, there may be others). As far as I know a plugin is the only way to 'do something' when webpack is done loading modules.
You still want a custom loader that is extracting the JSON from the output of the responsive-loader, as described above. It won't write each to disk, though. Instead your loader will call a method on the following module:
You also write a json-collector.js that is just a little node module that you will use to hold on to the JSON object you're building. This bit is awkward because it's separate from the loader but the loader needs it. This collector module is simple, though, and if you wanted to be cleaner you could turn it into a more generic module and treat it as a proper, separate node dependency. All it is is an object with a method for adding JSON data, which appends it to an internal JSON object, and one for reading out the collected data, which returns the JSON.
And then you have a plugin that hooks into the end of the build (I think there's one for 'build sealed' that I've used). When that hook is reached, you know webpack has no more modules to load, so the plugin now calls the 'read' method on the json-collector, gets the JSON object from it and writes that to disc.
This solution doesn't fit the standalone plugin/standalone loader convention in webpack but if that doesn't bother you it's actually pretty straightforward, each of the three pieces has a simple job to do. I've used this pattern multiple times and it's worked for me.

Svelte framework: pass environment variables to client-side bundle at runtime

Posted this to the Svelte repo as well:
I just made my first Svelte app over the weekend, and really liked the experience. One thing I'm curious about, that I wasn't able to figure out with a decent amount of research, is if/how one could pass a runtime env var or similar to a client-side script so it's available in the bundle/browser. This probably isn't considered a "best practice", so maybe I'm just on my own here, but in Pug for example you can do something like the following (from a Hapi.js route handler for example):
const context = {
foo: bar,
baz: ''
}
return h.view('index', context)
These vars are then available in the Pug context.
In my toy app I wanted to make it possible to pass an api key at server start time (either from a .env or CLI), and inject that from the Express server like so:
app.use(express.static(`${__dirname}/public`))
and have that var be available in the client script. Again, it's probably not a best practice to be injecting api keys into client-side scripts and making calls from there, but is this kind of variable passing possible in Svelte?
It seems like this should be possible using either rollup-plugin-inject or rollup-plugin-replace, but I wasn't able to figure out how to make that work. This is definitely not a criticism of the framework, but perhaps a section on working with env vars would be a useful addition to the Svelte docs. Thanks!
Typically this is the sort of thing you would do in your build config. From the rollupjs tag I'll assume you're using that — you could use rollup-plugin-replace to inject the content you need:
// rollup.config.js
import replace from 'rollup-plugin-replace';
import svelte from 'rollup-plugin-svelte';
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife'
},
plugins: [
svelte(),
replace({
// you're right, you shouldn't be injecting this
// into a client script :)
'API_KEY': process.env.API_KEY
})
]
};

Categories

Resources