Can't import .obj files into my Nuxt components - vue.js

in my Nuxt project I have a background scene made with Three.js.
Now I want to load an .obj into this scene. So the model has to loaded via the component.
my index.vue component:
export default {
name: 'scene',
data () {
return {
}
},
mounted () {
if(!this.scene) this.scene = new Scene({
$canvas: this.$refs.canvas,
});
}
}
In my .js file(Inside the components, where the .vue is as well):
import * as THREE from "three";
import Common from "../Common";
import { OBJLoader2 } from '~/node_modules/three/examples/jsm/loaders/OBJLoader2.js';
const Model = require('#/assets/models/background_1.obj')
export default class Model_1{
constructor(){
this.init();
}
init(){
var loader = new OBJLoader2();
console.log(Model)
loader.load(Model, (root) => {
Common.scene.add(root);
});
}
}
The Nuxt config:
export default {
mode: 'universal',
build: {
vendor: ['hammerjs'],
extend (config, ctx) {
config.module.rules.push(
{
test: /\.(obj|gltf)$/i,
loader: 'file-loader',
}
);
}
}
}
Following error appears:
Cannot find module '#/assets/models/background_1.obj'
I though that the .vue component will look into the assets folder, gets the obj and just reflects the url. But it's looking for a module, which I don't really understand 🤷‍♂️
The .obj file is located in the assets/models folder.

Ok, although every doc said that if the file is in static/file you'll have to use the src static/file. Now that did not work for me, but just using file as source worked. It's working, but can someone please clarify this since I've been on this problem since 2 days and many migraines 😐

Transfer the file to static folder example static/images/background.png
Then omit the #/assets/
var textureURL = "images/background.png";
var texture = textureLoader.load(textureURL);

Related

Get config value in vue file

possibly a very simple question: I need to get a configuration value from within an html block in a vue file.
I have this simple config.js
const env = process.env.NODE_ENV
const development = {
images: {
server: "http://localhost:4001",
}
}
const production = {
images: {
server: "http://someimageserver.com",
}
}
const config = {
development,
production,
}
module.exports = config[env]
And this simple vue.js
<template>
<div>
<img :src="`${config.images.server}/images/someimage.jpg`"/>
</div>
</template>
At run time, the above throws
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'images')
What should I do to make this work ?
Thanks in advance
Note: I can get configuration values from within the script block using, this works perfectly, for example
import config from "../../config"
...
var c = config.images.server
UPDATE:
Using vue 3, one can easily achieve this by adding
import config from "../config"
app.config.globalProperties.$config = config
to the main.js file. From there on, $config can be used in templates and scripts across all files. Source: https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-prototype-replaced-by-config-globalproperties
In Vue, you need to initiate a variable and assign what you imported to it, and eventually return this variable. It looks like below:
Vue2:
import config from "../../config"
export default {
data() {
return {
config: config
}
}
}
Vue3:
import config from "../../config"
export default {
setup() {
return {
config
}
}
}
Then the url in the template should work fine.
-------------------------updates-----------------------
If you want to use config globally, you can register it as a Plugin.
Create plugin.js
import config from "../../config"
export const Config = {
install(Vue, options) {
Vue.prototype.$config = function() {
return config
}
}
}
Then, in your main.js, add below code
import * as Plugins from '#/plugin.js'
Vue.use(Plugins.Config.install)
Then you can use $config within templetes like $route without any other import. Surely you can write other global functions in plugin.js and register each of them in main.js.

How to add included Pug files to Vite module graph

I wrote a Rollup plugin to import Pug as an HTML string:
// Rollup plugin imported to Vite config
import { render } from 'pug';
export default function pug() {
return {
name: 'rollup-plugin-pug-html',
transform(src, id) {
if (id.endsWith('.pug')) {
const html = render(src, { filename: id });
const code = `export default ${JSON.stringify(html)};`;
return { code };
}
},
};
}
I'm using it in Vite to create templates for Vue components, as in this reduced example:
// ProofOfConceptSFC.vue
<script>
import { compile } from 'vue/dist/vue.esm-bundler.js';
import template from './template.pug';
export default {
render: compile(template)
};
</script>
The HMR is working great when I edit template.pug. The new template appears and the latest reactive values persist.
My problem is that template.pug may depend on other Pug files with include:
//- template.pug
include ./header.pug
p Hello {{ name }}
include ./footer.pug
The Vite server doesn't know about those files, and nothing happens if I touch them. Ideally I could invalidate template.pug when any Pug file is changed.
I'm guessing I want my plugin to update the ViteDevServer's server.moduleGraph. Is there a supported way to do that?
Huge thanks to the friendly Vite chat on Discord for setting me in the right direction.
The two keys I was missing:
Use Pug compile to create a render method that has render.dependencies, as done by Parcel
Use virtual import statements to attach the dependencies to the transform hook result, as done by vite-plugin-svelte.
Here is the working plugin:
import { compile } from 'pug';
export default function pluginPug() {
return {
name: 'vite-plugin-pug',
transform(src, id) {
if (id.endsWith('.pug')) {
const render = compile(src, { filename: id });
const html = render();
let code = '';
for (let dep of render.dependencies) {
code += `import ${JSON.stringify(dep)};\n`;
}
code += `export default ${JSON.stringify(html)};`;
return { code };
}
},
};
}

How to mock modules in storybook's stories?

I have a Vue component which includes some external modules with complicated logic. For example:
// Component.vue
import Vue from 'vue';
import { externalModule } from '#/path/to/module';
export default {
methods: {
useExternalModule() {
externalModule.doSomethig();
}
}
};
Is it possible to mock the externalModule inside the story?
I'm using Storybook v6.
You can create a __mocks__ folder to put your mock components in. Then in your .storybook/main.js file use this to point webpack to your mock file.
module.exports = {
// your Storybook configuration
webpackFinal: (config) => {
config.resolve.alias['externalModule'] = require.resolve('../__mocks__/externalModule.js');
return config;
},
};
This is covered in the docs under "Mocking imports".
However, this is a global configuration and not a story level configuration.

This relative module was not found: * ../services/Repository, Vue error

[SOLVED] services/ folder was at the same level than src/ , putting it inside src, following Vue.js Style guide, solved the error. Thanks guys.
When I run npm run serve I get that error, reading over (a lot) SO similar questions and trying everything didn't work, I don´t even know where that line ../services/Repository comes from (I changed the import path in BrandList.vue and nothing changes).
Here is my Repository.js
import http from "../http-common";
class Repository {
getAll() {
return http.get("/index");
}
}
export default new Repository();
This is where I import it, components/BrandList.vue
<script>
import Repository from "../services/Repository";
export default {
name: "brands",
data() {
return {
brands: []
};
},
methods: {
retrieveTutorials() {
Repository.getAll()
.then(response => {
this.brands = response.data;
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
},
mounted() {
this.retrieveTutorials();
}
};
</script>
Project tree
It should be ../../services/Repository as it's two steps up in the file tree.
From your screenshot you can immediately notice that the services directory is on the same level as the src. A simple fix would be moving the services directory into the src directory.
If you do not want to do that, you can change the import path from "../services/Repository" to "../../services/Repository".
Furthermore, if your project was created with the Vue CLI then the # import only works for files and directories in src/. You could update that if you wanted to.

Vue Relative Paths with the CLI Service

Running into a problem which is surely related to Webpack.
Tried to do the most basic of services as a smoke test (start small) in a Vue app created by the CLI.
Versions:
Vue CLI: 3.11.0
vue 2.6.10
#vue/CLI-Service 4.0.5
I created a folder called shared inside the src folder of my project. The HelloWorld.vue file is in the components folder. In that file, I imported a data service which I placed inside shared and attempted to use it in the Created event of the HelloWorld component:
<script>
import { dataService } from "../shared";
export default {
name: "HelloWorld",
props: {
msg: String
},
created() {
dataService.addWebSite();
}
};
</script>
The data service is very simple and just meant to hit an API (data.service.js):
import * as axios from 'axios';
const addWebSite = function () {
axios({
method: 'POST',
url: 'https://localhost:44362/WebSites/CreateWebSite',
data: {
name: "Pluralsight",
url: "http://Pluralsight.com"
}
}).then((response) => {
var discard = response.data;
return discard;
});
};
export const dataService = {
addWebSite: addWebSite
};
When I execute npm run serve, I see the following error message:
ERROR Failed to compile with 1 errors 6:13:39 PM
This relative module was not found:
../shared in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/HelloWorld.vue?vue&type=script&lang=js&
I'm guessing this is some kind of Webpack relative path thing, but am at a loss and have not been able to solve it using Google.
The vue.config.js looks like this:
module.exports = {
configureWebpack: {
devtool: 'source-map',
}
};
And I have tried adding a publicPath property of both './' and '/' to that exported object.
Anyone know what's going on?
When you try to import from a folder instead of file, like this
import { dataService } from "../shared";
it implies that you actually want to import from "../shared/index.(any_supported_extension)". But since your file is actually named data.service.js you will have to change your import to
import { dataService } from "../shared/data.service.js";