How can I extract specific css file from vue cli? - vue.js

I have two files black-variables.scss, white-variable.scss in my project, what I expect is other than bundle as main.js and main.css, I want to export these two file after bundling process, so I can get the result like
main.js
main.css
black-variables.css
white-variable.css
How can I get the result by setting vue.config.js? I have tried used ChunkName to import scss,
import(/* webpackChunkName: "white-theme" */ '#/scss/base/_white_root_color_vars.scss');
import(/* webpackChunkName: "black-theme" */ '#/scss/base/_white_root_color_vars.scss');
So that I can get output two CSS file white-theme, black-theme, however I don't want to import it into my JS, is there any way else to reach my goal?
Thank you in advance.

Related

Import Vue components from folder programmatically not hard coded (I'm actually using Nuxt but I'll call it Vue)

I have a number of SVG cards as components in Vue; I probably have 50 or more. I could import them one by one just after the script tag:
<script>
import MyVueComponent1 from "~/components/MyVueComponent1.vue";
import MyVueComponent2 from "~/components/MyVueComponent2.vue";
import MyVueComponent3 from "~/components/MyVueComponent3.vue";
...
import MyVueComponent50 from "~/components/MyVueComponent50.vue";
But I've been reading that I can do this programmatically. I just haven't found any one example that makes it crystal clear to me. I able to register the components dynamically but I'm not certain how to import an entire folder of components.
I was able to register the components dynamically using this code in the created hook:
created() {
const requireComponent = require.context(
// Look for files in the current directory
"../components",
// Do not look in subdirectories
false,
// Only include "S" prefixed .vue files
/S[\w-]+\.vue$/
);
// For each matching file name...
requireComponent.keys().forEach((fileName) => {
// Get the component config
const componentConfig = requireComponent(fileName);
// Get the PascalCase version of the component name
fileName = fileName.replace("./", "");
fileName = fileName.replace(".vue", "");
const componentName = fileName;
this.generatedComponentList.push(componentName);
// Globally register the component
Vue.component(componentName, componentConfig.default || componentConfig);
});
},
And I'm using the generatedComponentList of component names to display the cards:
<div
v-for="componentName in generatedComponentList"
:key="componentName"
>
<component :is="componentName" :id="componentName"></component>
</div>
But I'd love to get rid of all the import lines under the script tag and have cleaner and more dynamic code. That way if I add a new component card to the folder, it will simply be "picked up" and displayed without having to add the "import" line, or register the component etc. Hopefully I've clearly articulated what I'm looking to achieve.
Nuxt auto-imports the components you use from the ~/components directory, so you don't need to import or register them explicitly.
This feature is enabled in nuxt.config.js with the components config:
// nuxt.config.js
export default {
components: true
}
Thanks tony19 suggesting I look at the nuxt.config.js file, your answer definitely put me on the right track; also thanks to whoever suggested 1 might be the right answer.
Here's the solution that worked for me:
Based on tony19's suggestion I looked at my nuxt.config.js file; specifically the component section. I already had this line in my code to automatically import any components in my components folder:
components: true,
But the components I wanted to import were nested within another folder within the components folder.
After reading this 2 from the nuxt.org docs, I replaced my previous code with this:
//components: true,
components: [
// Equivalent to { path: '~/components' }
'~/components',
{ path: '~/components/myTargetComponents', extensions: ['vue'] }
],
Then, I was able to remove all of my import lines:
<script>
import MyVueComponent1 from "~/components/MyVueComponent1.vue";
import MyVueComponent2 from "~/components/MyVueComponent2.vue";
import MyVueComponent3 from "~/components/MyVueComponent3.vue";
...
import MyVueComponent50 from "~/components/MyVueComponent50.vue";
In my index.vue file I don't have anything listed in the components section anymore...just this as a reminder to myself:
,
components: {
//see nuxt.config.js file ...component section
},
Just to be clear, in my index.vue file, I don't import any components using this format, "import MyVueComponent1 from "~/components/MyVueComponent1.vue"; AND I don't have anything listed in the components section. Also just to clarify, the components I'm wanting to import ARE in a sub folder of the components folder (~/components/myTargetComponents). I realize now that I didn't clearly articulate that in my original post.
As a related piece of this...
As you can see from my original post, I'm using a block of code in the created hook to populate a list of the component names:
this.generatedComponentList.push(componentName);
And then using this list to iterate through the component cards:
<div
v-for="componentName in generatedComponentList"
:key="componentName"
>
<component :is="componentName" :id="componentName"></component>
</div>
But I'm wondering if there's a list of these components already generated by nuxt.config.js file. Any suggestions? And again, thanks everyone for the help, I greatly appreciate it.

Nuxt: how to explicitly name JS chunks?

I'm using Nuxt in static site generation mode. One requirement in my project is to deploy only certain routes, each with their respective assets.
But Nuxt gives chunks random names like 925446d.js.
So I created a manual router.js and specified chunk names while importing my components:
component: () => import(/* webpackChunkName: "about" */ '~/pages/about.vue').then(m => m.default || m)
But Nuxt doesn't take my chunk names into account and continues to give chunks random names, making it super difficult to single out which chunk goes with which route.
Any suggestion?
If you want to be able to identify chunks by name, Nuxt actually has a built-in mechanism do to that, using the property filename of the build config.
You can add the following in your nuxt.config.js file:
{
// ...
build: { filenames: { chunk: () => '[name].js' } }
}
Some additional options do exist, see documentation.

Component dynamic import doesn't work from router.js

With Nuxt.js, in my router.js I'm trying to import my route component thus:
{
path: '/',
component: () => import(/* webpackChunkName: "index" */ '~/pages/index.vue')
}
I get this error:
render function or template not defined in component: anonymous
I came across someone else's Nuxt.js project where they add the following at the end, and with this it works:
{
path: '/',
component: () => import(/* webpackChunkName: "index" */ '~/pages/index.vue').then(m => m.default || m)
}
The returned object of my import() looks like this:
In a another Vue.js, non-Nuxt project, the same kind of import() looks like that:
In both cases, the component is nested in some "default" object. But with Nuxt.js it seems you must import that object explicitly, whereas with regular Vue.js you don't have to specify that.
Why?
Regarding why the module is nested inside a { default } object: it's because Nuxt uses ES6 style modules. ES6 style modules are written the following:
export default {
// some object
};
Default is not the only property you can have. More syntax.
Regarding why vue-router are working without the .default, it's because the code is more versatile than the code used by Nuxt. Nuxt already ships it's own builder and always uses ES6 modules.
On the other hand, vue-router does not know about how it will be built. So to be easier to use, vue-router automatically checks if the module is ES6 or not.
const resolve = once(resolvedDef => {
if (isESModule(resolvedDef)) {
resolvedDef = resolvedDef.default
}
// ...
}
Source: code of vue-router.
As you may already know, it's very uncommon to use a router.js file in a Nuxt project, because Nuxt already has its own routing system which splits your code into chunks for each page. Documentation here.

vue and webpack doesn't do lazy loading in components?

The lazy component in vue/webpack seem to be wrong or I miss confuse about the terms.
To do lazy loading of component I use the keyword import and webpack should split this component to sepeate bundle, and when I need to load this component webpack should take care of it and load the component.
but in fact, webpack does make sperate file, but it loaded anyway when the application is running. which is unexpected.
For example I just create a simple vue application (using the cli) and browse to localhost:8080/ and the about page should be loaded (by default) using the import keyword.
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
So This is by design? I load every time the file I do not need right now (the page about). and if I have 200 pages, when I'll fetch 200 files I dont need. how that ends up? that did I save here by using the import key?
In vuetify for example they uses import key, but the files are loaded anyway and not by demand.
You can also avoid component prefetch using one of the webpack "magic" comments (https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules), eg.
components: {
MyComponent: () => import(/* webpackPrefetch: false */ './MyComponent.vue')
}
Feel free to read more about this Vue optimization below:
https://vueschool.io/articles/vuejs-tutorials/lazy-loading-individual-vue-components-and-prefetching/
If you're referring to the default app template from Vue CLI, then you're actually observing the prefetch of the About page, intended to reduce load times for pages the user will likely visit.
If you want to avoid this performance optimization, use this Vue config:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugins.delete('prefetch')
config.plugins.delete('preload')
}
}
For troubleshooting reference, Chrome's Network panel includes an Initiator column, which provides a clickable link to the source file that triggered the network call. In this case of the about.js, the source file looks like this:
try using vue-lazyload maybe it can help and for <script> tags you can try async defer it helps in website speed optimizations

entrypoint size limit: code splitting to limit the size of entrypoints in vue cli 3.x

I get the following warning after building my project with vue cli 3:
After some look up I found out that there is no need to create a webpack.config.js as it is written here (or here):
The initial project doesn't require the file to exist because you just created a project with fresh "default" settings that don't require any config.
The Vue CLI documentation offers a vue.config.js which is optional and will be automatically loaded if it's present in the project root. Also it seems possible to work with webpack in the vue.config.js like this.
I'm totally new to webpack and couldn't figure out how to limit the size of my entrypoints with the code splitting that is provided in the message of the warning abouve. Can somebody please give me a hint how to solve this using the vue.config.js file?
We can also split each route's component into separate chunks and only load them when the route is visited.
In your router.js file:
// replace
// import UserDetails from './views/UserDetails'
// with
const UserDetails = () => import('./views/UserDetails')
const router = createRouter({
// ...
routes: [{ path: '/users/:id', component: UserDetails }],
})
For further information read the official documentation.
Try to load your components asynchronously.
Also prefer local component registration over global.