How can I use fontawesome icons in a laravel application using vite? - laravel

I have installed #fortawesome/fontawesome-free package using npm. The latest Laravel application uses vite by default. I am unable to solve this issue. Any help would be much appreciated. My vite.config.js is
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { viteStaticCopy } from 'vite-plugin-static-copy';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
'resources/admin/css/app.css',
'resources/admin/js/app.js',
'resources/css/glide.css',
'resources/js/glide.js',
'resources/js/Sortable.js',
'resources/js/tinymce.js',
'resources/sass/app.scss',
'resources/admin/sass/app.scss',
]),
{
name: 'blade',
handleHotUpdate({ file, server }) {
if (file.endsWith('.blade.php')) {
server.ws.send({
type: 'full-reload',
path: '*',
});
}
},
},
viteStaticCopy({
targets: [
{
src: 'node_modules/#fortawesome/fontawesome-free/webfonts',
dest: '',
},
],
}),
],
});
I imported fontawesome scss files in app.scss. My app.scss file contains
#import "#fortawesome/fontawesome-free/scss/fontawesome";
#import "#fortawesome/fontawesome-free/scss/brands";
#import "#fortawesome/fontawesome-free/scss/regular";
#import "#fortawesome/fontawesome-free/scss/solid";
#import "#fortawesome/fontawesome-free/scss/v4-shims";
I tried using a third party library https://github.com/sapphi-red/vite-plugin-static-copy to copy webfonts of fontawesome package. Is there a better way than this?

I solved it by first installing sass pre-processor:
npm install -D sass
after that I imported all fontawesome scss files into my app.js file:
import './bootstrap';
import '#fortawesome/fontawesome-free/scss/fontawesome.scss';
import '#fortawesome/fontawesome-free/scss/brands.scss';
import '#fortawesome/fontawesome-free/scss/regular.scss';
import '#fortawesome/fontawesome-free/scss/solid.scss';
import '#fortawesome/fontawesome-free/scss/v4-shims.scss';
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();

It is quite easy if you are not adding it via npm. Copy entire fontawesome dir into resources dir (/resources/fontawesome), then declare variable in your scss file like (assuming you are doing it in a file inside /resources/sass:
$fa-font-path: '../fontawesome/webfonts';
and import fontawesome files:
#import '../fontawesome/scss/brands';
#import '../fontawesome/scss/solid';
#import '../fontawesome/scss/light';
#import '../fontawesome/scss/fontawesome';
Build script will copy files to your /public/build/assets dir and change urls and dev script will load them from your resources dir.

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.

Vite does not build my #extend rules from bulma-scss

I'm having a build issue with the scss at-rule "extend" using Vite to build out a Vue3 component library using the bulma-scss NPM package.
Using Bluma buttons for example, I would like to import the bulma-scss button.scss file into my tag in my .vue file (or into the button.scss file and then import that into the script tag) like so:
<template/>
<script/>
...
<style lang="scss">
#import 'bulma-scss/elements/button';
</style>
When running $ vite build I get this error from Vite:
File: /Users/my-user/sites/component-library/node_modules/bulma-scss/elements/_button.scss
Error: The target selector was not found.
Use "#extend %control !optional" to avoid this error.
It is specifically this line in the bulma-scss package that it doesn't like (in this example) https://github.com/j1mc/bulma-scss/blob/master/elements/_button.scss#L71
it looks like I can get around this by adding the following preprocessor option to my storybook's vite configs:
css: {
preprocessorOptions: {
scss: {
additionalData: `#import "bulma-scss";`
}
},
},
But that would include the entirety of bulma-scss right? Ideally I would only import the things I need from bulma.
And here is my entire vite config file (sans the css preprocessorOptions)
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import {resolve} from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
name: 'lmsComponentLibrary',
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue',
},
},
},
},
resolve: {
alias: {
'bulma-scss/': require('path').join(__dirname, 'node_modules/bulma-scss/'),
}
},
});
I think the problem comes from the bulma-scss package itself. In the file that you are importing there is no %control placeholder. Even its import ../utilities/controls and ../utilities/mixins don't have that placeholder neither. So the error is expected here.
The %control is defined in bulma-scss/utilities/extends so you can fix the problem by importing that file. BUT, it will lead to another problem because in the _extends.scss there are some variables that are not defined. So you need to import all the file that contains these variables.
Luckily, the package has a file containing all the utility variables. So you just need to import it.
#import 'bulma-scss/utilities/all'; <-- Add this line
#import 'bulma-scss/elements/button';

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.

Bootstrap-Vue CSS compilation in Laravel Mix

I'm using Laravel 5.6, Laravel Mix 2.0, and Bootstrap-Vue 2.0.0-rc.1.
Trying to find a way to configure Laravel Mix to include Bootstrap-Vue's CSS into my app.css file and prevent Bootstrap-Vue from including <style> tags into the page <head>.
I saw this note in the package docs but still not sure how to use this properly:
Note: requires webpack configuration to load css files (official guide)
Finally, found a solution - ExtractTextPlugin.
let mix = require('laravel-mix');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
mix.webpackConfig({
module: {
rules: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
}
});
Reference: https://github.com/JeffreyWay/laravel-mix/issues/1589
Install:
npm i bootstrap-vue
npm install --save-dev style-loader css-loader
Use:
edit resources/js/app.js to:
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue)
edit resources/sass/app.scss to:
Import the styles:
import '~bootstrap/dist/css/bootstrap.css'
import '~bootstrap-vue/dist/bootstrap-vue.css'
Make sure the app.js and app.css are included in the blade(view) that is acting as the container for your vue.
See: https://bootstrap-vue.js.org/docs/

Custom version of bootstrap using webpack/laravel mix?

I'm trying to create a custom build of bootstrap 4 using webpack, but it won't compile.
I have bootstrap 4 here:
/node_modules/bootstrap/scss
I create my own app.scss file to import the various parts of bootstrap that I want:
#import "variables";
#import "mixins";
#import "custom";
....
In my webpack file I have:
mix.sass('resources/assets/sass/app.scss', 'public/css', null, { includePaths: ['node_modules/bootstrap/scss/'] });
I've also tried:
mix.sass('resources/assets/sass/app.scss', 'public/css', { includePaths: ['node_modules/bootstrap/scss/'] });
You can import bootstrap in app.scss with:
..
#import "~bootstrap/scss/variables"
#import "~bootstrap/scss/mixins"
..
The ~bootstrap is resloved to the npm package. This way you won't have to configure the mix file.

Resources