Blank Page on production using Laravel Mix - laravel

I built a single page application (SPA) using Laravel 8 + Vue.js + InertiaJs. Everything is working fine in the development environment, but when I compile assets for production, it shows me a blank page, and there is no error in the console. All assets are loading correctly with a 200 code, and everything seems to be OK, but the Vue app is not mounting!
webpack.mix.js
const mix = require('laravel-mix');
require('laravel-mix-workbox');
mix.webpackConfig({
output: {
filename: '[name].js',
chunkFilename: 'js/[name].js',
}
}).js('resources/js/app.js', 'public/js')
.extract(['vue'])
.version();
Image1
Image2
Image3

try using the inertiajs webpack.mix.js provided by the pingCRM github:
const path = require('path')
const mix = require('laravel-mix')
const cssImport = require('postcss-import')
const cssNesting = require('postcss-nesting')
/*
|--------------------------------------------------------------------------
| 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()
.postCss('resources/css/app.css', 'public/css', [
// prettier-ignore
cssImport(),
cssNesting(),
require('tailwindcss'),
])
.webpackConfig({
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'#': path.resolve('resources/js'),
},
},
})
.version()
.sourceMaps()
note you may have to follow the instructions for setting up tailwindcss which can be found here, only do this if you plan to use it otherwise remove the require('tailwindcss'), from the webpack file
you also may need to npm install --save-dev postcss-import and npm install --save-dev postcss-nesting the --save-dev flag will add it to your package.json file for future reference

Related

CSS isn't working in production environment with Laravel Mix 5

This is for my Laravel + Vue SPA app.
I have this Laravel Mix config file here:
const path = require('path');
const fs = require('fs-extra');
const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss');
require('laravel-mix-bundle-analyzer');
function publishAssets() {
const publicDir = path.resolve(__dirname, './public');
if (mix.inProduction()) {
fs.removeSync(path.join(publicDir, 'dist'));
}
fs.copySync(path.join(publicDir, 'build', 'dist'), path.join(publicDir, 'dist'));
fs.removeSync(path.join(publicDir, 'build'));
}
mix.js('resources/js/app.js', 'public/dist/js')
.sass('resources/sass/app.scss', 'public/dist/css').options({
postCss: [tailwindcss('./tailwind.config.js')],
processCssUrls: false,
});
// alias the ~/resources folder
mix.webpackConfig({
plugins: [
// new BundleAnalyzerPlugin()
],
resolve: {
extensions: ['.js', '.json', '.vue'],
alias: {
'#': `${__dirname}/resources`,
'~': path.join(__dirname, './resources/js'),
ziggy: path.join(__dirname, './vendor/tightenco/ziggy/dist/js/route.js'),
},
},
output: {
chunkFilename: 'dist/js/[chunkhash].js',
path: mix.config.hmr ? '/' : path.resolve(__dirname, './public/build'),
},
});
mix.then(() => {
if (!mix.config.hmr) {
process.nextTick(() => publishAssets());
}
});
It works fine with npm run watch, but when I do npm run production, the CSS doesn't work. The site loads and works, but the CSS is missing.
Can anyone see what in my code is causing it?
Here's my spa.blade.php:
<link rel="stylesheet" href="{{ mix('dist/css/app.css') }}">
...
<script src="{{ mix('dist/js/app.js') }}"></script>
In the network tab of Chrome dev tools, the CSS file is 270kb in develop environment and 42kb in prod environment.
Something is getting translated wrong.
In my case, it cause by setting wrong property "purge" in tailwindcss config file.
When I ran "npm run hot" or "npm run dev", the website was fine.
But it broke when I ran "npm run prod".
It seems the dev mode ignore the property "purge".
I'm calling this solved for now because my site started working.
it was extremely difficult to navigate since I had 6 months of work on a dev branch, and it worked via npm run watch. When I merged into master, npm run production loaded incorrectly--the styles were half there and half missing.
The solution was to downgrade from tailwindcss#1.9 to tailwindcss#1.4.
Along my way, I read something about postcss or something not working with the --no-progress flag which is on npm run production.
A person could try removing that flag, but I already downgraded tailwind so I didn't try that.

How to precache static assets with laravel-mix-workbox?

I'm trying to build a PWA with offline support using Laravel and Vue.js. I'm using the laravel-mix-workbox plugin to setup my service worker, but I'm having a massive amount of trouble trying to accomplish what should be a simple task. I have some static assets (images, XML files etc.) that are served out of my application, and I can't get workbox to add them to the precached file list.
I have tried moving the assets to /resources/img and adding a call to copyDirectory to try to get them included, also, I have tried the webpack-copy-plugin, but only the compiled assets are included(js, css, fonts etc). Here is my webpack.mix.js file:
const mix = require('laravel-mix');
//mp035 add workbox plugin and copy-webpack-plugin
require('laravel-mix-workbox');
const CopyPlugin = require('copy-webpack-plugin');
/*
|--------------------------------------------------------------------------
| 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.
|
*/
//mp035 fix issue with laravel-mix outputting bad urls in precache manifest for app.js (//js/app.js) and app.css
// and copy assets into place (so they are in the build tree)
mix.webpackConfig({
output: {
publicPath: ''
},
plugins: [
new CopyPlugin([
{ from: 'resources/img/*', to: 'public/img', flatten:true },
{ from: 'resources/root/*', to: 'public', flatten:true },
]),
],
})
.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.sourceMaps().version()
// mp035 add inject manifest plugin to inject workbox manifest into the service worker.
.injectManifest({
swSrc: './resources/pwa/service-worker.js',
maximumFileSizeToCacheInBytes: 20000000, // ******************************DEBUG ONLY!!!
});
Does anyone know how I can include all files in my /resources/img (or /public/img) in the precached files list?
Ok, so it looks like this is an issue with laravel-mix-workbox. Removing it and using the generic workbox webpack plugin solves the problem. For anyone finding this, here is the updated webpack.mix.js:
const mix = require('laravel-mix');
//mp035 add workbox plugin and copy-webpack-plugin
const CopyPlugin = require('copy-webpack-plugin');
const {InjectManifest} = require('workbox-webpack-plugin');
/*
|--------------------------------------------------------------------------
| 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.
|
*/
//mp035 fix issue with laravel-mix outputting bad urls in precache manifest for app.js (//js/app.js) and app.css
// and copy assets into place (so they are in the build tree)
mix.webpackConfig({
output: {
publicPath: ''
},
plugins: [
new CopyPlugin([
{ from: 'resources/img/*', to: 'public/img', flatten:true },
{ from: 'resources/root/*', to: 'public', flatten:true },
]),
new InjectManifest({
swSrc: './resources/pwa/service-worker.js',
maximumFileSizeToCacheInBytes: 20000000, // ******************************DEBUG ONLY!!!
}),
],
})
.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.sourceMaps().version();
All in all, using workbox with laravel-mix has been an extremely painful process with all of the 'minor' tweaks that laravel-mix does breaking the workbox plugin. I'd recommend sticking to plain webpack if possible.

Webpack Laravel-Mix Chunk error TypeError: "e[r] is undefined"

Am building a web application with Vue and Laravel.
Am utilizing code splitting and versioning with Laravel mix and Webpack under the hood.
However, whenever i make changes to my code, run npm run production and upload on the live server, on frequent occations i receive TypeError: "e[r] is undefined"
I have to manually clear browser cache before the page loads correctly.
I already have versioning enabled and thus cache busting should be automated.
Below is my webpack.mix.js file
const mix = require('laravel-mix');
const webpack = require('webpack');
mix.webpackConfig({
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
})
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
plugins: [new CompressionPlugin()],
optimization: {
minimize: true,
namedModules: true,
namedChunks: true,
removeAvailableModules: true,
flagIncludedChunks: true,
occurrenceOrder: false,
usedExports: true,
concatenateModules: true,
sideEffects: false, // <----- in prod defaults to true if left blank
}
};
/*
|--------------------------------------------------------------------------
| 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/main/main.js', 'public/v1.4.0/js')
.sass('resources/sass/app.scss', 'public/css')
.extract(['vue'])
.version();
I had a similar problem and I found a solution that wasn't quite good but it worked: set in webpack config options optimization.concatenateModules and optimization.minimize to false.
After a lot of hustle,
my best approach was to control cache from the server software itself.
Ex: you can prevent JS and CSS caching from nginx / apache/http configurations

How to resolve aliases in mocha-webpack for laravel vue single file components

I am using vuejs in Laravel 5.7 to build an SPA. I am using mocha-webpack and vue-test-utils to write some vue component tests.
The tests can't seem to work out stylesheet imports into components. For example: I have a ExampleComponent.vue which includes the following:
</script>
<style lang="scss" scoped>
#import '#/_variables.scss';
.subpanel-control > ul > li {
background-color: lighten($body-bg, 50);
margin-left: 10px;
height: 25px;
width: 25px;
line-height: 25px;
color: $body-bg;
}
when running npm run test I get the following error:
Error in ./resources/assets/js/components/Panel.vue?vue&type=style&index=0&id=21f01f46&lang=scss&scoped=true&
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
#import '#/variables';
^
Can't find stylesheet to import.
╷
98 │ #import '#/variables';
│ ^^^^^^^^^^^^^
╵
stdin 98:9 root stylesheet
in C:\Users\jjackson\Documents\projects\wave\resources\assets\js\components\Panel.vue (line 98, column 9)
I can't work out why it doesn't understand the alias #. Here is my webpack.mix.js:
let mix = require('laravel-mix');
const path = require('path');
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.sass('resources/assets/sass/nifty.scss', 'public/css', {
implementation: require('node-sass')
})
.sass('resources/assets/sass/themes/type-b/theme-ocean.scss', 'public/css')
.less('resources/assets/less/bootstrap-4-utilities.less', 'public/css')
.webpackConfig({
resolve: {
alias: {
'#': path.resolve('resources/assets/sass'),
'~': path.resolve('resources/assets/js')
}
}
})
.sourceMaps();
if (mix.inProduction()) {
mix.version();
}
Any help would be appreciated
While struggling with the same issue I landed on this page - https://github.com/vuejs/vue-cli/issues/4053 and a comment from robbishop that lead me to my solution.
Using the above I managed to find a configuration in webpack.mix.js that seem to work:
First install null-loader (npm i -D null-loader)
Add the following line in rules:
{ test: /\.scss$/, use: [{ loader: 'null-loader' }] }
My webpack.mix.js looks like that:
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')
.webpackConfig({
module: {
rules: [
{ test: /\.scss$/, use: [{ loader: 'null-loader' }] }
]
},
resolve: {
alias: {
'#': path.resolve('somepath/sass')
}
}
})
.sass('some/path/app.scss', 'some/path/css');
My unit tests are now executed while having scss imports in my components.
This turned out to be a docker problem. Was trying to run npm run dev outside of the docker environment, and it was causing this error. When I ran all npm commands inside of the container everything worked fine

How to load bootstrap-vue into Laravel 5 with laravel-mix?

I am trying to load Bootstrap Vue into a Laravel 5.6 project
The official docs say to modify your webpack.config.js file like:
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ 'style-loader',
+ 'css-loader'
+ ]
+ }
+ ]
+ }
Webpack docs: https://webpack.js.org/guides/asset-management/#loading-css
I don't have a webpack.config.js file so I tried loading the CSS in with Laravel mix
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.styles('node_modules/bootstrap-vue/dist/bootstrap-vue.css', 'public/css');
This give me an error
mix.combine() requires a full output file path as the second argument.
and I'm not convinced it's the right way to do it.
What is the proper way to add bootstrap-vue into a new Laravel 5.6 project?
Import the Bootstrap Vue styles in your app.scss file directly, instead of through mix:
// app.scss
#import "~bootstrap/dist/css/bootstrap.css";
#import "~bootstrap-vue/dist/bootstrap-vue.css";
// webpack.mix.js
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
Laravel Mix already has the CSS loader configured so you don't need to set up a separate webpack.config.js file.

Resources