Laravel Mix and Vue custom Loader (iView) - vuejs2

I'm kinda new to programming with frameworks like VueJs and webpack is completely new for me. Right now we are working with Laravel 5.6 and laravel mix. I don't know if vue-loader is already in laravel.mix but I'm using a Vue Component Framework called iView and I need to load a custom Loader according to their page how to set it up: https://www.iviewui.com/docs/guide/iview-loader-en
The problem is it just doesn't work.
Nothing gets rendered and I get this error everytime:
[Vue warn]: Failed to mount component: template or render function not
defined.
Here's my webpack.mix.js
mix.webpackConfig({
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
}
},
{
loader: 'iview-loader',
options: {
prefix: true
}
}
]
}
]
}
})
But when I remove the section with loader: 'vue-loader' then everything gets rendered as it should but the custom loader is still not working since I get errors like this when using the kebap case name.
[Vue warn]: Unknown custom element: - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
Anyone good at Laravel who knows how to solve this? Thanks in advance.
cheers

Related

How do I handle the new isCustomElement setup for using web components in Vue 3 when unit testing with Jest

I am trying to write unit tests for my Vue 3 app using web components.
I have Jest configured containing transform options:
// ...
"transform": {
".*\\.(vue)$": "vue-jest",
"^.+\\.js$": "babel-jest"
},
// ...
I need to use isCustomElement which is now required at compilation time, so I’ve added options based on the proposed solution in Vue3 docs like I did in webpack. I played around with it in the transform and global options. And also tried adding it to my babel.config.
// ...
"transform": {
".*\\.(vue)$": ["vue-jest", {
compilerOptions: {
isCustomElement: tag => tag === 'my-custom-component'
}
}],
"^.+\\.js$": "babel-jest"
},
// ...
However it’s still throwing a Vue warn when running tests:
[Vue warn]: Failed to resolve component: my-custom-component.
Any ideas how to make isCustomElement work with Jest? I am at a loss as to what I need to set up to get rid of the console warnings and properly render the web components. In Vue 2 I just had to add them to setupFiles directly.

How can I modify a Vue Loader setting in Laravel Mix?

Using Laravel Mix by the way... and trying to use Vue Apollo, it says we need to add this to babel config:
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
transpileOptions: {
transforms: {
dangerousTaggedTemplateString: true
}
}
}
}
]
},
but that is giving me Failed to mount component: template or render function not defined. error that I haven't been able to find a solution for, except for a thread somewhere in Google saying it's because I'm using vue-loader twice..
So, what I'm trying to do now that may fix this error is to apply that dangerousTaggedTemplateString setting to the existing webpack configuration for .vue files.
Anyone knows how to do that?
Try this (untested), leave the mix.js line you mentioned untouched.
Then on a new line:
mix.options({
vue: {
transpileOptions: {
transforms: {
dangerousTaggedTemplateString: true
}
}
}
});

How to correctly render info to handlebars template

Rendering information from my controller only passes information through to the partials included on the template.
Here is how I go about it in my login controller. After I check password and username provided I send two objects to the dashboard template that I would like to render to the page
res.render(path.join(DIST_DIR, 'dashboard.hbs'), {
user,
company
});
I can log this info and can see that it exists and it also renders out in the partials that included on dashboard.hsb, but it seems that dashboard itself is not getting the data.
My webpack setup
{
// Loads the javacript into html template provided.
// Entry point is set below in HtmlWebPackPlugin in Plugins
test: /\.hbs$/,
loader: 'handlebars-loader',
query: {
partialDirs: [
path.join(__dirname, './src/views/partials')
],
helperDirs: [
path.join(__dirname, './src/helpers')
]
}
},
new HtmlWebPackPlugin({
filename: 'dashboard.hbs',
title: 'Dashboard',
chunks: ['dashboard', 'dashboard~login', 'vendors~dashboard', 'vendors~dashboard~login'],
template: 'src/views/index/dashboard.hbs',
excludeChunks: ['server']
}),
So the page renders fine and the user information that I try to pass does show up in the partials (used by dashboard layout), but the information for the user that I want to display in the body of dashboard.hbs is always blank. I seems that information is not passed to this template.
Where am I going wrong? I would really appreciate some help here.
I was using the wrong loader. Instead of using handlebars-loader, I updated the code to use the html-loader
{
// Loads the javacript into html template provided.
// Entry point is set below in HtmlWebPackPlugin in Plugins
test: /\.hbs$/,
loader: 'html-loader',
query: {
partialDirs: [
path.join(__dirname, './src/views/partials')
],
helperDirs: [
path.join(__dirname, './src/helpers')
]
}
},
And now everything works as expected. Hope this helps someone else down the line

Package vue components that use class syntax

I have a hard time packaging our components as an npm package so we can reuse them in other projects.
I have the feeling I searched everywhere on the internet to no avail. I'm suspecting that using our components in the class syntax style makes most, if not even all, examples fail for me.
The final and most successful so far was the one from the Vue documentation
However with that one I get an error:
[!] (buble plugin) SyntaxError: Unexpected character '#'
The reason for that is obviously the class syntax with #Component immediately failing the build. Is there a way to make this work with class syntax?
My component's script part looks like this (nothing special on the css and template parts):
<script>
import { Vue, Component, Prop } from 'vue-property-decorator';
#Component
export default class Checkbox extends Vue {
#Prop({default: false}) checked;
};
</script>
I think that the problem is with installing vue-loader and vue-template-compiler together.
I'm Quoting Vue-loader Vue Docs
The plugin is required! It is responsible for cloning any other rules
you have defined and applying them to the corresponding language
blocks in .vue files. For example, if you have a rule matching
/\.js$/, it will be applied to <script> blocks in .vue files.
After you npm install them, you need to change your webpack.config.js file like this
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// ... other rules
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// make sure to include the plugin!
new VueLoaderPlugin()
]
}

responsive-loader with nuxt.js

I want to integrate responsive-loader into my Nuxt.js project which runs in SPA mode. (Optional I want to add Vuetify Progressive Image support also).
It will be a static hosting with Netlify.
Versions:
"nuxt": "^2.3.4"
"responsive-loader": "^1.2.0"
"sharp": "^0.21.1"
I found some solutions how to do it (https://stackoverflow.com/a/51982357/8804871) but this is not working for me.
When I run npm run build
I get an error message: "TypeError: Cannot set property 'exclude' of undefined"
My build section looks the following:
build: {
transpile: [/^vuetify/],
plugins: [
new VuetifyLoaderPlugin()
],
extractCSS: true,
/*
** Run ESLint on save
*/
extend(config, { isDev, isClient, isServer }) {
// Default block
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
if (isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vuetify/]
})
]
}
// Default block end
// here I tell webpack not to include jpgs and pngs
// as base64 as an inline image
config.module.rules.find(
rule => rule.loader === "url-loader"
).exclude = /\.(jpe?g|png)$/;
/*
** Configure responsive-loader
*/
config.module.rules.push({
test: /\.(jpe?g|png)$/i,
loader: "responsive-loader",
options: {
min: 350,
max: 2800,
steps: 7,
placeholder: false,
quality: 60,
adapter: require("responsive-loader/sharp")
}
});
}
}
The error is probably found in this section:
config.module.rules.find(
rule => rule.loader === "url-loader"
).exclude = /\.(jpe?g|png)$/;
Like said I get this error message: "TypeError: Cannot set property 'exclude' of undefined".
I run this project along with vuetify. I also would like to enable the Progressive image support together with responsive loader. Does anybody know how to setup both rules together?
https://github.com/vuetifyjs/vuetify-loader#progressive-images
The easiest way to integrate responsive-loader into a Nuxt.js project is to use this module: https://www.npmjs.com/package/nuxt-responsive-loader
Disclaimer: I created the module
The problem with your config that it relies on rule.loader property but rule can be defined in use or oneOf config sections as well.
Another one problem is that nuxt internal config has several rules with url-loader(for images, videos, fonts ...).
In your case the rule, you tried to find, has use section and url-loader is defined there, that's why your find function found nothing and threw this error:
{
"test": /\.(png|jpe?g|gif|svg|webp)$/,
"use": [{
"loader": "url-loader",
"options": {
"limit": 1000,
"name": "img/[hash:7].[ext]"
}
}]
}
About responsive-loader, you should remove extensions you want to process with responsive-loader from url-loader rule to avoid unexpected behavior and conflicts, here is extend function working example:
extend(config, ctx) {
let imgTest = '/\\.(png|jpe?g|gif|svg|webp)$/';
// find by reg ex string to not rely on rule structure
let urlRule = config.module.rules.find(r => r.test.toString() === imgTest);
// you can use also "oneOf" section and define both loaders there.
// removed images from url-loader test
urlRule.test = /\.(svg|webp)$/;
config.module.rules.push({
test: /\.(png|jpe?g|gif)$/,
loader: "responsive-loader",
options: {
// place generated images to the same place as url-loader
name: "img/[hash:7]-[width].[ext]",
min: 350,
max: 2800,
steps: 7,
placeholder: false,
quality: 60,
adapter: require("responsive-loader/sharp")
}
})
}
Yes, it looks dirty, but I think it's only way for now to change some loader.
What about vuetify - I think both loaders will conflict with each other and probably the solution is to use single loader that will work with your images.
Hope it helps.
Update for Nuxt >= 2.4.0:
They modified the rules array please update the following line:
let imgTest = '/\\.(png|jpe?g|gif|svg|webp)$/i';
Then the code should work normally again.