Add tailwindcss to lucky framework - laravel-mix

I've created a new project using the lucky framework and want to add tailwindcss. I have added it using these steps:
yarn add tailwindcss (https://tailwindcss.com/docs/installation)
npx tailwindcss init (https://tailwindcss.com/docs/configuration)
Added this to webpack.mix.js (https://tailwindcss.com/docs/installation)
mix.postCss('src/css/main.css', 'public/css', [
require('tailwindcss'),
])
Added the following to src/css/main.css:
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
When I run lucky dev the assets are compiled but text isn't changed like in this basic example:
li class: "p-3 text-orange-800" do
text "Modify this page: src/pages/me/show_page.cr"
end
I seem to miss some steps to make it work in this framework.

I don't think your webpack.mix.js content is quite right.
You can see how I set up Tailwind CSS in a Lucky Application in this RailsByte, but basically:
Add const tailwindcss = require("tailwindcss"); somewhere at the top of webpack.mix.js.
Add this to your .options() hash in webpack.mix.js, assuming your Tailwind config is in the root directory of your project:
processCssUrls: false,
postCss: [ tailwindcss("./tailwind.config.js") ],
These are all pretty much from the Laravel Mix setup in the Tailwind Guides themselves, here: https://tailwindcss.com/docs/installation#build-tool-examples

Related

Laravel Mix (v6.16.0) ignores tailwind.config.js (v1.2.0) settings

I am using laravel/framework v6.16.0, laravel/ui v1.2.0 and TailwinCSS v1.2.0. For setting up, I used the instructions from https://sandulat.com/blog/installing-tailwind-into-laravel/. After minor adjustments concerning the namings, like
tailwind.js => tailwind.config.js
#tailwind preflight; => #tailwind base;
#import 'tailwind'; => #import 'tailwindcss';
everything seemed to work fine and the TailwindCSS classes take effect. My only problem is, that all changes I made in tailwind.config.js are ignored. The files are recompiled (npm run watch), but the changes from tailwind.config.js are not adopted. There are no error messages or other indications.
If I provoke a syntax error in tailwind.config.js, I get an error message. Therefore I conclude that the file is parsed, but as I mentioned without any effect.
Can someone tell me where to start troubleshooting or better tell me where the error could be?
These settings are working for me in a fresh project with Laravel 8, Mix 6, and Tailwind v2:
tailwind.config.js
This file is unmodified except for the added purge settings:
module.exports = {
purge: [
'resources/views/**/*.blade.php',
'resources/js/**/*.js',
'./resources/**/*.vue',
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
webpack.mix.js
This file is unmodified except for the import for tailwind and the appended tailwind settings. Watchout for that extra {} in the second parameter there.
const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.vue()
.sass('resources/sass/app.scss', 'public/css', {}, [
tailwindcss('tailwind.config.js'),
])
.options({
processCssUrls: false,
});
app.scss
I just added all three tailwind directives for now. The output is quite large, so some editing may be recommended.
#tailwind base;
#tailwind components;
#tailwind utilities;
The URL in the other answer was critical to making it work. This one here: https://laracasts.com/discuss/channels/elixir/multiple-tailwind-configs-for-theming
This Laracasts user's comment:
https://laracasts.com/discuss/channels/elixir/multiple-tailwind-configs-for-theming
solved this issue for me.
I needed to call mix.sass with [tailwindcss: configfile] as the third parameter. Using the same in .options did not work.
Alright, installing https://github.com/laravel-frontend-presets/tailwindcss solved my problem.

How to migrate from laravel mix to pure Webpack?

Given the webpack.mix.js of a fresh Laravel project :
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
What is the equivalent using just webpack and a webpack.config.js? (Im looking to remove laravel mix as a dependency on an existing project.)
I did find this default file in the source but it did not help me. Is there a way I can see the "compiled/resulting" webpack configuration or a template/starting point that corresponds to laravel mix default settings?
You can, but the result is not very satisfactory.
Create a JS script with this:
console.log (JSON.stringify(
require('./node_modules/laravel-mix/setup/webpack.config.js'), null, 4)
);
and save it in the root folder of your laravel project. Run it with Node and the output will be the configuration object Laravel Mix receives and inputs to webpack.
However, this file is very long and covers a vast amount of settings, which you wouldn't need if you made your file from scratch. Yes, you could try and remove every extra setting you think you can remove without breaking your output, but in the end it's better to learn how Webpack works so you can write better, mode adjusted configs. At least you can use it to understand how it does certain things.
Just put into webpack.mix.js
Mix.listen('configReady', function (config) {
RegExp.prototype.toJSON = RegExp.prototype.toString;
console.log(JSON.stringify(config));
});
So you will get webpack config from your laravel.mix.
With recent laravel-mix you just need to invoke mix.dump() (in the webpack.mix.js script).
The file you referenced seems to point exactly to the default configuration. Why did this not help?
In order to migrate you could
Learn the basics
Extract the dependencies from Laravel mix aÇıd add them to your package.json
Hint: The dependencies there are your devDependencies
Start by installing npm install --save-dev everything "webpack", "babel" and prefixed with "-loader".
If you need Sass and extracted css - npm install --save-dev node-sass sass-loader mini-css-extract-plugin.
Minimal example of a webpack config for your mix example from above would be
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './resources/js/app.js',
output: {
filename: 'js/[name].js',
path: path.join(__dirname, 'public')
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css'
})
],
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'sass-loader'
]
}
]
}
};
Learn the more advanced basics for your use case

How to remove #charset in the CSS file when running npm?

I'm using Laravel 5.7 and i'm applying AMP to our website. (https://amp.dev/).
I'm folowing these steps to convert HTML to AMP: https://amp.dev/documentation/guides-and-tutorials/start/converting/?format=websites
One of the requirements is to replace external stylesheets to internal stylesheets (https://amp.dev/documentation/guides-and-tutorials/start/converting/resolving-errors?format=websites#replace-external-stylesheets). I've done this by doing the following code below:
<style amp-custom>
{!! file_get_contents(public_path('css/app.css')) !!}
</style>
I'm using Sass and I'm using Laravel mix to compile my assets.
This is my webpack.mix.js
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.sourceMaps()
.version();
But upon doing this I've encountered an error in the AMP:
CSS syntax error in tag 'style amp-custom' - saw invalid at rule '#charset'.
To solve this problem, I must remove the #charset "UTF-8"; in the compiled css css/app.css. And it seems that running npm run dev, its automatically adding #charset "UTF-8"; at the top of the file. How do I remove this?
I'm thinking that I have to add some code in the webpack.mix.js to remove that. But I don't have an idea how to do this.
Yep! SASS adds this directive if your SASS contains any extended (e.g., not standard ASCII) characters. There's an open issue in the SASS project to provide an option to not do this... but they've said they won't provide that option.
For now, it's pretty easy to fix... simply add a step that your build process that hunts for #charset "UTF-8"; and removes it. You can see how I did it here:
https://github.com/ampproject/samples/blob/master/amp-camp/gulpfile.js#L63
gulp.task('styles', function buildStyles() {
const cssEncodingDirective = '#charset "UTF-8";';
return gulp.src(paths.css.src)
... (stuff removed)
.pipe(options.env === 'dev' ? replace(cssEncodingDirective, '') : noop())
... (more stuff removed)
});
If you run 'npm run production', that line will be deleted automatically and you will not get an error in AMP validation.

Adding datatable to laravel mix files

I have installed datatables with npm by help of this doc, now I'm not sure how I can add datatables css and js files to my app.css and app.js
Downloaded files by NPM
Code
my webpack.mix.js
const mix = require('laravel-mix');
//laravel default to make app.css and app.js
// I want add Datatables to these files
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
//my template files
mix.combine([
'public/theme/primary/js/jquery.min.js',
'public/theme/primary/js/popper.min.js',
'public/theme/primary/js/bootstrap.min.js',
'public/theme/primary/js/uza.bundle.js',
'public/theme/primary/js/default-assets/active.js'
], 'public/js/combined.js');
Any idea?
Solved
I added this code to my bootstrap.js under require('bootstrap');
require( '../../node_modules/datatables.net/js/jquery.dataTables.js' );
require( '../../node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js' );
and then added styles to my app.scss
#import '~datatables.net-bs4/css/dataTables.bootstrap4.css';
Everything works perfectly now.
Hope it help others.
To combine multiple scripts and styles you can do it this way:
mix.scripts([
'node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js',
'resources/js/app.js'
])
.styles([
'node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css',
'resources/sass/app.scss'
]);
This by default should create all.js and all.css files in the respective js and css public folders.

How to #import external SCSS properly with webpack and Vue.js?

As in Material Component Web's example, I want to be able to import SCSS from my node_modules like this:
#import '#material/elevation/mdc-elevation';
However, I'm getting this error message when trying to run the webpack build:
File to import not found or unreadable: #material/elevation/mdc-elevation.
#import './~/#material/elevation/mdc-elevation.scss'; doesn't work either.
I'm pretty sure the issue is somewhere in my webpack config, but I can't figure out where.
What did they do in Material Components Web's Vue.js example in order to make it work?
Here's my npm-debug.log in case you need it.
And here's the corresponding Git repository: sk22/spg-tinf-sem03/proj01
Thanks in advance!
Edit: I want to be able to import the scss files, not the compiled css.
Got it.
here's a part of my webpack 2 config's module.rules:
{
test: /\.(sass|scss)$/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
includePaths: [path.resolve(__dirname, 'node_modules')],
},
},
],
},
So what did I do wrong?
My options object was placed in the rule directly, not the loader.
The old webpack config rule looked like this:
{
test: /\.(sass|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
options: { includePaths: [path.resolve(__dirname, './node_modules')] },
},
See the difference? Instead of the 'sass-loader' string, I extended it to an object, containing the loader name and the options object, because the options only apply to the sass-loader.
(You could also drop the path.resolve and only write 'node_modules', but it might be safer to leave it.)
Check out this documentation page for further information. https://webpack.js.org/configuration/module/#rule-use
Without that loader, you must prefix each import with a ~, which webpack converts to the node_modules folder, at least with my previous configuration.
But this will break 3rd party SCSS frameworks like Material Components Web, because they use #import statements without a leading ~ themselves, for example here.
Inside .vue files
This will not work in .vue files, as vue-loader just uses sass-loader without any options by default.
So if you want that to work, you probably need to make use of vue-loader's own options, as described in its documentation.
(I'm unable to get it to work for some reason I don't know...)
EDIT: Webpack has a section on sass-loader now: https://webpack.js.org/loaders/sass-loader/ also mentioning includepaths.
I had the same issue with #material and Vue. I managed to resolve the problem without adjusting the use property directly.
Solution
Step 1: First create a default Vue 2.1 project using the CLI.
Your file structure will have a ./build directory.
Step 2: Open the file 'utils' you will see a cssLoaders() function which returns an object/map for the languages vue-loader supports.
You will see both sass and scss in that map.
Step 3: Change the values of sass and scss to:
sass: generateLoaders('sass', {
indentedSyntax: true,
includePaths: [path.resolve(__dirname, '../node_modules')]
}),
scss: generateLoaders('sass', {
includePaths: [path.resolve(__dirname, '../node_modules')]
}),
Step 4: Go to the .vue file you're using and change the lang attribute in your <style> element to either sass or scss.
Step 5: After you've done that go to the terminal/console and install sass-loader with:
npm install sass-loader node-sass webpack --save-dev
Step 6: Then run npm run dev and it should work.
Why does this work?
Libraries
I dug around a bit and it turns out sass-loader uses node-sass which has some options such asincludePaths one mentioned by #22samuelk. IncludePaths tells node-sass or rather the underlying library LibSass to include sass files from that directory/path.
Vue
Sass-loader options
By default Vue expects your assets to be in your projects src/assets folder (correct me if I'm wrong). You can however use ~ to indicat you want to start at your projects root which would look like `~/node_modules/#material/smth/mdc-smth.scss.
Now if you want your sass-loader to use something other than those options you need to explicitly tell them.
Hence path.resolve(__dirname, '../node_modules' since the utils file is in ./build and you need to use an absolute path for sass-loader to understand where to look.
Vue-loader config
This is not really specific to the question but the vue-loader config defined in vue-loader.conf.js works as follows:
It uses the map returned by cssLoaders() to build the loaders expected by webpack.
The returned map ({key:value}) is then used by providing key as a file extension used in test: for a loader object. The value is used as the loader object.
Which would like like this:
{
test: /\.(key)$/,
use: [
{
loader: '//ld//-loader',
options: {
/*Options passed to generateLoaders('//ld//', options)*/
},
},
],
}
Where key is the file extention. In this case that would be either sass or scss. And //ld//is the loader you which to use. Which is shown in Step 3 as 'sass'.
Hopefully this clears up some stuff. Took me a while because I just started using Vue.

Resources