Webpack 5 & Vue 3 - CSS Tree Shake - javascript

I'm developing a UI component library using Vue 3, SCSS and Webpack 5. The library consists of serval components (button, input, form etc) having a scoped SCSS each.
After installing the library in my main project (also built with Vue 3 & Webpack 5), I'm importing only a single component (button) into it. However, after the build finished (CSS build) I see other components's CSS are included in the build as well. I should mention The JS tree shaking do working.
I want to reduce my bundle size to include only the CSS of the imported components.
An example for button component in my build file:
var script$4 = defineComponent({
name: "SButton",
props: {
stype: {
type: String,
default: "primary"
},
type: {
type: String,
default: "button"
}
}
});
const _withId$4 = /*#__PURE__*/withScopeId("data-v-7a74475b");
const render$4 = /*#__PURE__*/_withId$4((_ctx, _cache, $props, $setup, $data, $options) => {
return (openBlock(), createBlock("button", {
class: ["s-button", _ctx.stype],
type: _ctx.type
}, [
renderSlot(_ctx.$slots, "default")
], 10 /* CLASS, PROPS */, ["type"]))
});
var css_248z$6 = "html {\n --sbutton-general-icon-padding: 9px;\n --sbutton-general-icon-width: 36px;\n --sbutton-general-icon-height: 36px;\n --sbutton-width: 100%;\n --sbutton-min-height: 56px;\n --sbutton-line-height: 32px;\n}\n#media (min-width: 992px) {\n html {\n --sbutton-general-icon-padding: 7px;\n --sbutton-general-icon-width: 32px;\n --sbutton-general-icon-height: 32px;\n --sbutton-width: auto;\n --sbutton-min-height: 46px;\n --sbutton-line-height: 22px;\n }\n}";
styleInject(css_248z$6);

Related

gatsby-image-plugin - Node process "SIGABRT"error

I'm having issues with graphql when trying to use gatsby-plugin-image. My node process crashes with error "SIGABRT" which indicates some kind of critical node memory threshold has been reached.
As per the docs I have tried using graphql page queries, and useStaticQuery within a hook component.
The images folder is in src at root, and only has around 150 images in it.
I'm struggling to find any docs or examples of best practice for working with dynamic GatsbyImage as I'd like to pass the image as a prop.. can anyone shed any light on this? It seems width and or layout properties are required for the graphql query, as reducing the width of each image right down to 100 sometimes lets the process run and build complete. But it is intermittent, and crashes sometimes.
example page query:
export const Images = graphql
query {
allFile(filter: { extension: { regex: "/(jpg)|(jpeg)|(png)/" }, relativeDirectory: { regex: "/(events)/" } }) {
edges {
node {
id
base
name
relativePath
childImageSharp {
gatsbyImageData(width: 100, placeholder: BLURRED, formats: [AUTO, WEBP, AVIF])
}
}
}
}
}
;
example staticQuery:
const images = useStaticQuery(graphql
query {
allFile(filter: { extension: { regex: "/(jpg)|(jpeg)|(png)/" }, relativeDirectory: { regex: "/(events)/" } }) {
edges {
node {
id
base
name
relativePath
childImageSharp {
gatsbyImageData(width: 100, placeholder: BLURRED, formats: [AUTO, WEBP, AVIF])
}
}
}
}
}
);

LwcWebpackPlugin with AliasModuleRecord for lwc.dev isn't loading HTML file for component

I use LwcWebpackPlugin to load Lightning Web Components. Everything works fine but because I want to load compoennts from 'lwc' direcotry the namescape won't work. I must get components from /lwc directory and I bypysed this with AliasModuleRecord (described here) where I import all components by name. Problem is that only JS file is loading. Browser don't throw any exception but HTML body is not rendered. I know that JS file works because console log from connectedCallback is showed in browser console. What I'm doing wrong?. Maybe I haven't imported some library? Here is fragment form my webpack.config.js:
new LwcWebpackPlugin({
modules: [
{ dir: 'src/modules' },
{ npm: 'lightning-base-components' },
...glob.sync(
`./{${sfdxProjectJSON.packageDirectories?.map(package => package.path).join(',')}}/main/default/lwc/**/*.js`,
{ ignore: ['./**/__tests__/**'] }
).map(path => {
const name = path.split('/').at(-2);
return {
"name": `c/${name}`,
"path": path.replace('./', '')
};
}, {})
]
})
and this all resoults with:
[{
name: 'ui/helloWorldExampleOne',
path: 'pb-base/main/default/lwc/helloWorld/__docs__/examples/helloWorldExampleOne/helloWorldExampleOne.js'
},
{
name: 'ui/helloWorld',
path: 'pb-base/main/default/lwc/helloWorld/helloWorld.js'
},
{
name: 'ui/exampleOne',
path: 'pb-commerce/main/default/lwc/exampleOne/exampleOne.js'
}]

I can't make a dynamic background image in vuejs, the url doesn't work

Im trying to make 6 blocks with different background images, i tried different options but none of them works,
This works:
<div :style="{ backgroundImage: `url(${require('../assets/images/img/img-1.jpg')})` }"></div>
These two doesnt work even if 'test' is literally the right path for the img:
<div :style="{ backgroundImage: `url(${require(test)})` }"></div>
<div class="col-4 jum-block" :style="{ backgroundImage: 'url(' + require(test) + ')' }"></div>
<script>
export default {
name: "Component",
data() {
return {
test: "../assets/images/img/img-1.jpg",
cardImgPath: "../assets/images/img/",
images: [
{ img: "img-1.jpg" },
{ img: "img-2.jpg" },
{ img: "img-3.jpg" },
{ img: "img-4.jpg" },
{ img: "img-5.jpg" },
{ img: "img-6.jpg" },
],
};
},
};
</script>
Given the usage of require(), I'm assuming your project is a Webpack-based project (scaffolded from Vue CLI).
The require() argument cannot be a fully dynamic expression for the same reason that import() calls cannot:
Dynamic expressions in import()
It is not possible to use a fully dynamic import statement, such as import(foo). Because foo could potentially be any path to any file in your system or project.
The import() must contain at least some information about where the module is located. Bundling can be limited to a specific directory or set of files so that when you are using a dynamic expression - every module that could potentially be requested on an import() call is included. For example, import(`./locale/${language}.json`) will cause every .json file in the ./locale directory to be bundled into the new chunk. At run time, when the variable language has been computed, any file like english.json or german.json will be available for consumption.
// imagine we had a method to get language from cookies or other storage
const language = detectVisitorLanguage();
import(`./locale/${language}.json`).then((module) => {
// do something with the translations
});
In your case, you could change your require() argument to include the image's path directory:
<div v-for="image in images"
:style="{ backgroundImage: `url(${require('../assets/images/img/' + image.img)})` }" ></div>
<script>
export default {
data() {
return {
images: [
{ img: "img-1.jpg" },
{ img: "img-2.jpg" },
{ img: "img-3.jpg" },
{ img: "img-4.jpg" },
{ img: "img-5.jpg" },
{ img: "img-6.jpg" },
],
};
},
};
</script>

Gatsby i18next plugin No codeFrame could be generated

I'm developing a website with Gatsby and I wanted to implement multi-language support.
So I used the gatsby-plugin-react-i18next plugin.
I followed all the steps, but it doesn't work, once I log into my website this error message shows:
error message
Right now, my code is the next one.
gatsby-config.js
module.exports = {
siteMetadata: {
title: "Space",
},
plugins: [
"gatsby-plugin-postcss",
{
resolve: `gatsby-source-filesystem`,
options: {
name: `locale`,
path: `${__dirname}/locales`
}
},
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`, // name given to `gatsby-source-filesystem` plugin.
languages: [`en`, `es`],
defaultLanguage: `en`,
// if you are using Helmet, you must include siteUrl, and make sure you add http:https
siteUrl: `https://example.com/`,
// you can pass any i18next options
// pass following options to allow message content as a key
},
pages: [
{
matchPath: '/:lang?/blog/:uid',
getLanguageFromPath: true,
excludeLanguages: ['es']
},
{
matchPath: '/preview',
languages: ['en']
}
]
}
],
};
index.js
import * as React from "react"
import { graphql } from "gatsby"
import { useTranslation } from "gatsby-plugin-react-i18next"
export default function IndexPage() {
const { t } = useTranslation();
return (
<h1>{t("Space")}</h1>
)
}
export const query = graphql`
query($language: String!) {
locales: allLocale(filter: {language: {eq: $language}}) {
edges {
node {
ns
data
language
}
}
}
}
`;
And of course I have the translation folders project structure
Im trying this plugin on a new blank project, not on my main project, so I don't understand why the plugin fails.
Any thoughts? Thanks in advice!
Edit: I add the translation.json of the two languages
English
Spanish
Your JSONs looks and the implementation too (couldn't be wrong being that simple). So to me, the issue relies on the configuration. Try something simpler such as:
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`,
path: `${__dirname}/locales`,
languages: [`en`, `es`],
defaultLanguage: `en`,
i18nextOptions: {
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
keySeparator: false,
nsSeparator: false,
},
},
},

Vue 2 component styles without Vue loader

Considering that there is single file component (as shown in the guide),
<style>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
How can the same thing be done without Vue loader in non-modular ES5/ES6 environment?
Considering that the style is scoped,
<style scoped>
.example {
color: red;
}
</style>
Is there a way to implement scoped CSS in non-modular environment, too? If there's none, is there a way to implement it in modular environment (Webpack), but without Vue loader and custom .vue format?
Instead of using the template instance in the Vue component, you can harness a 'closer-to-the-compiler alternative' with the render function without the need for the Vue Loader or compiler. You can add any additional attributes with the second parameter in the createElement function and this will give you a lot of flexibility on top of just styles.
See the Render Functions section in the guide for more info and the full options allowed in the data obj:
https://v2.vuejs.org/v2/guide/render-function
https://v2.vuejs.org/v2/guide/render-function#The-Data-Object-In-Depth
Note: The caveat here is that the style will only apply to the component it is declared in, so it might not be able to used across multiple components of the same class like CSS would be. Not sure if thats also what you want to achieve.
An example from the docs catered to this use case:
Vue.component('example', {
// render function as alternative to 'template'
render: function (createElement) {
return createElement(
// {String | Object | Function}
// An HTML tag name, component options, or function
// returning one of these. Required.
'h2',
// {Object}
// A data object corresponding to the attributes
// you would use in a template. Optional.
{
style: {
color: 'red',
fontSize: '28px',
},
domProps: {
innerHTML: 'My Example Header'
}
},
// {String | Array}
// Children VNodes. Optional.
[]
)}
});
var example = new Vue({
el: '#yourExampleId'
});
It can be achieved putting the scope manually, as vue-loader does automatically.
This is the example of the documentation. Adding some kind of ID, "_v-f3f3eg9" in this case, to scope the class only for that element.
<style>
.example[_v-f3f3eg9] {
color: red;
}
</style>
Vue.component('my-component', {
template: '<div class="example" _v-f3f3eg9>hi</div>'
});
I use Rollup (+ Bublé) + Vue.js all the time. It's pretty simple and fast.
The Rollup config is like:
import vue from 'rollup-plugin-vue';
import resolve from 'rollup-plugin-node-resolve';
import buble from 'rollup-plugin-buble';
const pkg = require('./package.json');
const external = Object.keys(pkg.dependencies);
export default {
external,
globals: { vue: 'Vue' },
entry: 'src/entry.js',
plugins: [
resolve(),
vue({ compileTemplate: true, css: true }),
buble({ target: { ie: 9 }})
],
targets: [
{ dest: 'dist/vue-rollup-example.cjs.js', format: 'cjs' },
{ dest: 'dist/vue-rollup-example.umd.js', format: 'umd' }
]
};
I've made a boilerplate repo:
git clone https://github.com/jonataswalker/vue-rollup-example.git
cd vue-rollup-example
npm install
npm run build

Categories

Resources