Laravel mix removes subfolder from image path - laravel-mix

I've set up an alias for my public folder where I've placed my images.
So they are inside public/images. I have a subfolder for certain types of images - in this case, card brands.
They're in public/images/card-brands
Here is my alias config:
mix.webpackConfig({
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': __dirname + '/resources/js',
'#public' : __dirname + '/public'
},
},
})
I'm importing the images in my vue component file:
import amex from '#public/images/card-brands/amex.svg'
import discover from '#public/images/card-brands/discover.svg'
import visa from '#public/images/card-brands/visa.svg'
import mastercard from '#public/images/card-brands/mastercard.svg'
Then using it inside my components data like so:
export default {
name: 'PaymentMethod',
data() {
return {
...
visaSvg: visa,
mastercardSvg: mastercard,
discoverSvg: discover,
amexSvg: amex,
currentCardBrand: this.initialCurrentCardBrand
...
}
},
props: {
...
initialCurrentCardBrand: String,
...
}
computed: {
getCurrentCardBrandSvg() {
switch (this.currentCardBrand) {
case 'mastercard':
return this.mastercardSvg;
break;
case 'visa':
return this.visaSvg;
break;
case 'amex':
return this.amexSvg;
break;
case 'discover':
return this.discoverSvg;
break;
}
}
}
...
Finally, I'm using it on my template as and image src: <img class="w-10" :src="getCurrentCardBrandSvg">
Now, even though the images and my import path are using the card-brands subfolder, the URL that is generated ignores this and just looks for the images in the root images folder.
It should be:
/public/images/card-brands/visa.svg
but it's generating as
/public/images/visa.svg
How can I get it to keep my subfolder?

try this instead {{ asset('/images/card-brands/mastercard.svg')) }}
I faced a similar issue in laravel. I used the above format.Please correct me if Im wrong.

Edit: This could be slightly wrong. It works correctly for importing images via javascript, but I think grabbing images via laravel in blade templates still needs the images in the public folder.
The issue was not knowing that I was supposed to put my images folder inside the resources folder rather than public.
Laravel Mix will compile the images like it does the JS and SCSS and place it in public automatically.
So I created an images folder in resources, deleted my manually made images folder in public, and made an alias:
alias: {
'#images': __dirname + '/resources/images'
}
and now I can link to that inside my vue component.
import amex from '#images/card-brands/amex.svg'
import discover from '#images/card-brands/discover.svg'
import visa from '#images/card-brands/visa.svg'
import mastercard from '#images/card-brands/mastercard.svg'
The generated images will automatically be placed in public on the root level once I run npm run dev or npm run prod

Related

Multiple Tailwind CSS Configs

I am building a project using Laravel/Inertia/Vue and I am using Tailwind CSS.
I want to have separate admin.css and client.css files using tailwindcss 3.2 ability to have multiple config files:
./styles/admin.css
#config "./tailwind.admin.config.js"
#tailwind base;
#tailwind components;
#tailwind utilities;
but the problem is that Vite will build just app.css for me not the admin one
vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
ssr: 'resources/js/ssr.js',
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
ssr: {
noExternal: ['#inertiajs/server'],
},
server: {
host: "localhost",
},
});
app.css is imported in app.js
I can not figure it out
Could you please help me?
I want to have separate admin.css and client.css files per each tailwindcss config file.
You can pass an array of input files to vite as follows:
input: ['resources/js/app.js','resources/css/admin.css','resources/css/client.css']
This should result in seperate output files in your build directory.
If you want to keep the css as javascript import you can create a second InertiaApp for the admin area:
Copy app.js and rename it like 'admin.js'
Change css import in admin.js to '/styles/admin.css'
Change your vite input to: input: ['resources/js/app.js','resources/js/admin.js']
Use a different blade layouts for the 'admin' area with reference to admin.js instead of app.js : #vite('resources/js/admin.js')
Thanks #dustin for your answer. Here are some more things:
I can split javascript application by defining multiple rootViews using inertia-laravel#0.3.2 in HandleInertiaRequests.php middleware:
public function rootView(Request $request)
{
if ($request->routeIs('admin.*')) {
return 'admin';
}
return 'app';
}
And have two different apps.
But do you think its a good approach to have two different apps?
I like the separation idea but is it the right way?
I Also have concerns about bundling and mixing in inertia and ssr, would it be a problem for that when you have two apps? I dont know anything about inertia's way of working
I was hoping there is some other method like creating a higher order component or something like that. I am very new to Vue world and I am still trying to learn.

Disable asset handling in Vite

I have a PHP project (WordPress theme) with Vite and PostCSS to bundle my JS and CSS files.
The output directory is build and everything worked, but as soon as I import fonts or images in my CSS, Vite copies them into the build folder and changes the paths in the source.
File structure:
styles
|- tailwind.css
|- fonts
|- fa-brands-400.eot
|- fa-brands-400.woff
|- fa-brands-400.woff2
|- fa-brands-400.svg
|- fa-brands-400.ttf
js
|- index.js
vite.config.js
...
In my tailwind.css, I'm importing the font:
#font-face{
font-family:"Font Awesome 5 Brands";
font-style:normal;
font-weight:400;
font-display:block;
src:url(../styles/fonts/font_awesome/fa-brands-400.eot);
src:url(../styles/fonts/font_awesome/fa-brands-400.eot?#iefix) format("embedded-opentype"),url( ../styles/fonts/font_awesome/fa-brands-400.woff2) format("woff2"),url(../styles/fonts/font_awesome/fa-brands-400.woff) format("woff"),url(../styles/fonts/font_awesome/fa-brands-400.ttf) format("truetype"),url(../styles/fonts/font_awesome/fa-brands-400 .svg#fontawesome) format("svg")
}
The problem, Vite copied the imported font files to my build folder and my font import now looks like this (in build/tailwind.css:
#font-face{
font-family:"Font Awesome 5 Brands";
font-style:normal;
font-weight:400;
font-display:block;
src:url(/fa-brands-400.eot);
src:url(/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(/fa-brands-400.woff2) format("woff2"),url(/fa-brands-400.woff) format("woff"),url(/fa-brands-400.ttf) format("truetype"),url(/fa-brands-400.svg#fontawesome) format("svg")
}
Is there a way to disable this? I just want Vite to bundle my JS and CSS, but don't include my assets.
My vite.config.js looks like this:
import postcssImport from "postcss-import"
import tailwindcssNesting from "tailwindcss/nesting"
import tailwindcss from "tailwindcss"
import autoprefixer from "autoprefixer"
import postcssScss from "postcss-scss"
import { defineConfig } from "vite"
export default defineConfig({
build: {
outDir: "build",
cssCodeSplit: true,
emptyOutDir: true,
minify: false,
assetsDir: "",
rollupOptions: {
input: {
index: "js/index.js",
tailwind: "styles/tailwind.css",
},
output: {
entryFileNames: "[name].js",
assetFileNames: "[name].[ext]",
},
},
},
css: {
postcss: {
syntax: postcssScss,
plugins: [postcssImport, tailwindcssNesting, tailwindcss, autoprefixer],
},
},
clearScreen: true,
publicDir: false,
})
I am facing a similar issue with a library build. I want to have an image relative to my css file, but default it is placed at the root and the reference in the css file is also to the root (just like in your problem). I did not find a perfect solution, but I was able to place the image in the same folder as the css file, where the css file also references the image in the same folder. I used the rollup config option output.assetFileNames for this. You can pass your own function and in that function you can add the complete path to the folder where you want to add the asset.
assetFileNames: (assetInfo: PreRenderedAsset): string => {
if (assetInfo.type === 'asset') {
return 'styles/fonts/[name][extname]';
}
else {
return '[name][extname]';
}
},
This will place the fonts in the build/styles/font folder. The references in the css will also be in this folder.
There is one caveat: The references will begin with '/', so they will be from the root of the domain. I have not found a solution for this.

Can't add mathtype plugin locally in CKEditor

import React from 'react'
import CKEditor4 from 'ckeditor4-react'
export default function App () {
return (
<CKEditor4
data='<h1>hello</h1>'
config={{
extraPlugins: ['ckeditor_wiris'],
allowedContent: true,
height: 300,
startupFocus: 'end',
skin: 'moono'
}}
onBeforeLoad={(CKEDITOR) => {
CKEDITOR.plugins.addExternal(
'ckeditor_wiris',
'https://www.wiris.net/demo/plugins/ckeditor/',
'plugin.js'
)
}}
/>
)
}
I created a react app using CRA, this code will render CKEditor with Mathtype plugin.
I want to use mathtype from this package, https://www.npmjs.com/package/#wiris/mathtype-ckeditor4, locally instead of the path https://www.wiris.net/demo/plugins/ckeditor/.
CKEDITOR.plugins.addExternal(
'ckeditor_wiris',
'../node_modules/#wiris/mathtype-ckeditor4/',
'plugin.js'
)
But I'm getting an error when I change the mathtype path,
Since we can't directly access files from node_modules folder from CRA App, due to webpack configuration, we should copy #wiris/mathtype-ckeditor4/ folder to public folder at the build time.
To do that, first integrate react-app-rewired to customize webpack without ejecting it. And then install copy-webpack-plugin to copy files at a build time, finally inside config-overrides.js add this snippet to copy mathtype to mathtype-ckeditor4 folder inside public folder.,
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = function override (config, env) {
config.plugins.push(
new CopyWebpackPlugin({
patterns: [
{ from: 'node_modules/#wiris/mathtype-ckeditor4', to: 'mathtype-ckeditor4' }
]
})
)
return config
}
Lastly change the code inside onBeforeLoad to this,
CKEDITOR.plugins.addExternal('ckeditor_wiris', '/mathtype-ckeditor4/', 'plugin.js')
This way we can install and use mathtype locally in CKEditor.

How to load csv files into a nuxt vue component

I am currently trying to load a csv file into a Nuxt page. The folder structure is below and produces the error "Failed to load resource: the server responded with a status of 404 (Not Found)":
Project
|
+--pages
|
+--lesson
|
+--index.vue
+--file.csv
import * as d3 from 'd3';
export default{
data(){
return{
dataset1:[]
}
mounted(){
d3.csv('file.csv', (myData) => {
console.log('Mydta', myData);
this.dataset1 = myData;
})
}
}
I have added the following to the web pack config in the nuxt-folder:
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
config = {
module: {
rules: [
{
test: /\.csv$/,
loader: 'csv-loader',
options: {
dynamicTyping: true,
header: true,
skipEmptyLines: true
}
}
]
}
}
}
}
Thanks in advance
I recently had the same question and ended up using the #nuxt/content module – worked like a charm, didn't even need to include d3 (which is usually my go-to for parsing CSV files).
I believe the issue is you cannot access the csv file the way you are attempting to, the way to do that would be storing the file in the '/assets' directory which you can then access as shown in the docs I linked ~/assets/file.csv I think this is also a more correct location for storing such files to avoid having lingering files throughout the project
This worked for me:
async mounted() {
const d = await d3.csv("/data.csv");
console.log(d);
}
With data.csv placed in public folder.

Cannot retrieve images in my react component

I am quite new at coding so please be indulgent... I searched a lot and I don't manage to get my issue fixed :(
I would like to get my images rendered through and html img tag. I saw that the best way in react is to import my images. Like this :
import avatar from './avatar.png';
export default class Connection extends React.Component {
render () {
return (
<div>
{this.props.user.firstname} {this.props.user.lastname}
<img src={avatar} className='img-circle' />
<a href='#' onClick={this.props.logout}>Déconnexion</a>
</div>
);
}
}
I use the following webpack config to load these images :
module: {
loaders: [
{ test: /\.jsx?$/, exclude: [/node_modules/], loader: 'babel' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') },
{ test: /\.(png|gif|jpe?g|svg|jpg)$/i, loader: 'file-loader?hash=sha512&digest=hex&name=[path][name]-[hash].[ext]' },
{ test: /\.(png|gif|jpe?g|svg|jpg)$/i, loader: 'url-loader?limit=10000' }
]
}
I see that webpack manage to load the jpg or png files but when it comes to display it, it seems that the file generated/copied is not available (ex: /MyApp/avatar-50b93a2df8aec266d7c8c1c0f5719d1b.png is not available).
I use the webpack dev server so I don't see my files bundled and the dist or build folder created.
Any idea of solving my issue ?
Thanks,
When using the require within the img tag I get the following error :
Module not found: Error: Cannot resolve 'file' or 'directory' ./avatar
I tried to get the extension in the webpack config but it does not solve anything :(
Here is my public path config in my webpack config :
output: {
path: path.join(__dirname, '/build'),
publicPath: '/',
filename: 'bundle.js'
}
To load images with Webpack you need to do:
<img src={require('./avatar.jpg'})/>
Webpack crawls through your application codebase, code gets bundled into a single file however files are not kept in the same structure, by calling require Webpack will do dependency management for you, in this case the file will move around and code will be injected so it is pointing to it's bundled location.
You can take a look at this article from SurviveJS Book. Load Images Chapter

Resources