I'm creating a modular Laravel 5.2 app, which consists of a number of proprietary packages loaded on a Laravel installation using composer.
Each of the packages are responsible of managing its own assets (copy to public folder, compress, versioning, etc). To accomplish this, I have a gulpfile that uses elixir for each package, and then, they are loaded on the main gulpfile of the laravel installation.
This is the main gulpfile.js on the laravel installation:
var filesystem = require("fs");
var gulp = require('gulp');
var elixir = require('laravel-elixir');
gulp.task('default', function() {
runPackagesGulpFiles();
});
function runPackagesGulpFiles() {
var packagesPath = 'vendor/my-organization/';
filesystem.readdirSync(packagesPath).forEach(function (file){
try {
var gulpFilePath = packagesPath + file + '/resources/assets/gulpfile.js';
var fileStat = filesystem.statSync(gulpFilePath);
require('./' + gulpFilePath);
} catch (error) {
if (error.message.indexOf('no such file or directory') < 0) {
console.error(error.stack);
}
}
});
}
All the main gulpfile.js does, is execute the packages gulpfiles if they exist using a require() function.
The following is an example of a package gulpfile:
var elixir = require('laravel-elixir');
elixir(function(mix) {
mix.copy('vendor/my-organization/store-manager/resources/assets/js/', 'public/assets/js/elixir_components/store-manager/');
mix.version([
//Store structure versioning
'assets/js/elixir_components/store-manager/stores/store.js',
'assets/js/elixir_components/store-manager/stores/views.js',
'assets/js/elixir_components/store-manager/stores/models.js',
'assets/js/elixir_components/store-manager/stores/controllers.js',
//Store resources versioning
'assets/js/elixir_components/store-manager/resources/resources.js',
'assets/js/elixir_components/store-manager/resources/views.js',
'assets/js/elixir_components/store-manager/resources/models.js',
'assets/js/elixir_components/store-manager/resources/controllers.js',
//Store structure resources versioning
'assets/js/elixir_components/store-manager/structures/structure.js',
'assets/js/elixir_components/store-manager/structures/views.js',
'assets/js/elixir_components/store-manager/structures/models.js',
'assets/js/elixir_components/store-manager/structures/controllers.js',
]);
});
In a normal case scenario this works just fine. A normal case scenario being that the packages are loaded using composer.
However, for the development of the packages, I create a symbolic link in the vendor folder that points to the package folder in my local machine.
When I try to execute gulp in the development environment, I get a Cannot find module 'laravel-elixir' error:
[22:27:03] Using gulpfile ~/supermarket-cms/gulpfile.js
[22:27:03] Starting 'default'...
Error: Cannot find module 'laravel-elixir'
at Function.Module._resolveFilename (module.js:339:15)
at Function.Module._load (module.js:290:25)
at Module.require (module.js:367:17)
at require (internal/module.js:16:19)
at Object.<anonymous> (/home/vagrant/Code/store-manager/resources/assets/gulpfile.js:1:76)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Module.require (module.js:367:17)
[22:27:03] Finished 'default' after 12 ms
Problem that I solved by installing laravel-elixir globally. But after I do so, the gulp task ends and my assets are not being copied.
[21:25:02] Using gulpfile ~/supermarket-cms/gulpfile.js
[21:25:02] Starting 'default'...
[21:25:02] Finished 'default' after 3.78 ms
No error whatsoever appears. Hope someone can help me. Thank you.
I think you're going about this the wrong way. This requires a level of knowledge about the workings of each vendor package, which goes against the purpose of package managers.
Instead, you should be allowing all of the assets from your vendor package to be published.
You'll start by making sure that in your boot method you publish your assets accordingly:
$this->publishes([
__DIR__.'/path/to/assets' => resource_path('vendor/my-organization/'.$package_name),
], 'public');
//make sure to replace '/path/to/assets' with your packages asset path.
Then when executing
php artisan vendor:publish
Now all of your JavaScript and CSS will be pushed into it's respective location in your resource_path
resources/
vendor/
my-organization/
<package_name>
js/
Now just have your Gulp task watch concatenate and load all scripts from within /my-orginazation/**/js. So now you can just do something like this:
elixir(function(mix){
'vendor/my-organization/**/js/*.js',
}, 'public/js/outputfile.js, 'resources');
Do, npm install --global laravel-elixir before you say gulp
Related
I've been using Laravel for years, but I've never used NPM packages in my Laravel apps until now. I'm using Laravel Valet as my development environment.
I am trying to utilize a simple package that interfaces with the remove.bg js package but I can't get it working after hours of trying different things.
Here's what I've done:
Installed the package via npm install remove.bg.
The package was complaining that it couldn't find the modules that it depended on (unirest, http, etc), so I installed them via npm install and even added these fallbacks since it was complaining about Webpack 5 and polyfill:
My webpack.mix.js file:
mix.webpackConfig({
resolve: {
fallback: {
fs: require.resolve('browserify-fs'),
crypto: require.resolve('crypto-browserify'),
stream: require.resolve('stream'),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
path: require.resolve('path-browserify'),
zlib: require.resolve('browserify-zlib'),
},
},
});
In my resources/js/bootstrap.js I added:
import { RemoveBgResult, RemoveBgError, removeBackgroundFromImageBase64 } from 'remove.bg';
window.Removebg = require('remove.bg');
Run npm run dev with no errors.
Included <script src="{{ mix('/js/app.js') }}"></script> in my blade template.
However, when I view my page, I get these errors in the console:
app.js:137237 Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')
at Object.inherits (app.js:137237)
at Object../node_modules/browserify-zlib/lib/index.js (app.js:28688)
at __webpack_require__ (app.js:139212)
at Object../node_modules/unirest/index.js (app.js:131192)
at __webpack_require__ (app.js:139212)
at Object../node_modules/remove.bg/dist/index.js (app.js:108502)
at __webpack_require__ (app.js:139212)
at Module../resources/js/bootstrap.js (app.js:16242)
at __webpack_require__ (app.js:139212)
at Object../resources/js/app.js (app.js:16230)
I'm stumped. What am I doing wrong here?
You can missed on webpack.mix.js file
Add this line
mix.js('resources/js/app.js', 'public/js');
I've updated laravel-mix to version 4.0.12 and faced with broken build on the line in *.scss where I used a relative path to include background image
I got a next files structure
resources/
|-assets/
||-img/
|||-background.png
||-sass/
|||-footer.scss
my code in footer.scss is next
.footer {
background-image: url(../img/background.png)
}
My webpack.mix.js is next
const mix = require('laravel-mix');
const resourcesAssets = 'resources/assets/';
const dest = 'public/assets/';
mix
.copy(`${resourcesAssets}images`, `${dest}images`, false)
.sass(`${resourcesAssets}scss/footer.scss`, `${dest}css`);
During compling npm run prod I got
Module build failed (from ./node_modules/css-loader/index.js):
ModuleBuildError: Module build failed (from ./node_modules/resolve-url-loader/index.js):
Error: resolve-url-loader: CSS error
predicate must return an absolute path or the result of calling next()
at file://C:\xampp\htdocs\laravel-project\resources\assets\sass\footer.scss:2:3
at encodeError (C:\xampp\htdocs\laravel-project\node_modules\resolve-url-loader\index.js:218:12)
at onFailure (C:\xampp\htdocs\laravel-project\node_modules\resolve-url-loader\index.js:175:14)
at <anonymous>
at runMicrotasksCallback (internal/process/next_tick.js:122:5)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickCallback (internal/process/next_tick.js:181:9)
at runLoaders (C:\xampp\htdocs\laravel-project\node_modules\webpack\lib\NormalModule.js:301:20)
at C:\xampp\htdocs\laravel-project\node_modules\loader-runner\lib\LoaderRunner.js:364:11
at C:\xampp\htdocs\laravel-project\node_modules\loader-runner\lib\LoaderRunner.js:230:18
at context.callback (C:\xampp\htdocs\laravel-project\node_modules\loader-runner\lib\LoaderRunner.js:111:13)
at onFailure (C:\xampp\htdocs\laravel-project\node_modules\resolve-url-loader\index.js:175:5)
at <anonymous>
at runMicrotasksCallback (internal/process/next_tick.js:122:5)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickCallback (internal/process/next_tick.js:181:9)
error in ./resources/assets/sass/footer.scss
How can I fix this problem?
It's an URL rewriting thing in Webpack as Laravel Mix is built on top of Webpack. For CSS compilation, Webpack rewrites and optimizes any url() calls within your stylesheets.
However, according to the Laravel Docs:
Absolute paths for any given url() will be excluded from URL-rewriting. For example, url('/images/thing.png') or url('http://example.com/images/thing.png') won't be modified.
So, Mix tries to rewrite your CSS to sth. like:
.footer {
background-image: url(/img/background.png?<some-hash-identifier>)
}
In that case, you can disable url() like so and Mix will not touch url(../img/background.png) in your footer.scss:
mix.sass(`${resourcesAssets}scss/footer.scss`, `${dest}css`);
.options({
processCssUrls: false
});
The problem was in too new "resolve-url-loader": "^3.0.0".
After installing an intermediate version "laravel-mix": "~3" some time ago it was added to package.json.
Removing it and rerun build helps me to resolve the problem. laravel-mix added "resolve-url-loader": "2.3.1" after running npm run prod.
I installed the vue-spinner with npm install vue-spinner --save-dev,
and I am trying to use the spinner on my file, but when I use the import
import PulseLoader from 'vue-spinner/src/PulseLoader.vue'
I get this error:
node_modules/vue-spinner/src/PulseLoader.vue:1
<template>
^
My gulpfile is requiring vueify, here is it:
var elixir = require('laravel-elixir');
require('laravel-elixir-vueify');
elixir(function(mix) {
mix.sass('app.scss','public/assets/css/')
.browserify('Main.js');
});
You actually don't need to require laravel-elixir-vueify in your guilpfile, it's easier just to install the original vueify (version 9 for Vue 2.0):
npm install vueify --save-dev
Then add the following to your package.json:
"browserify": {
"transform": [
"vueify"
]
}
Now elixir will use the vueify transform automatically when browserify is called.
EDIT
I just took a look at the vue-spinner page and it says that when using browserify you need to do the following:
import { PulseLoader } from 'vue-spinner/dist/vue-spinner.min.js'
So that may fix your problem without the vueify step, however, I still recommend avoiding the elixir add ons for the time being because their versioning is all over the place at the moment with Elixir 6 about to be released and Vue 2 being newly implemented in laravel.
Laravel elixir already comes with bunch of its own dependent node modules. How to use that modules instead of creating dependency in the root package.json.
For example, I want to use "del" package which is already there in /node_modules/laravel-elixir/node_modules/del, so rather than mentioning it on the /package.json, how can use this one?
You could try to set up your gulp file like this:
var gulp = require('gulp'),
del = require('del');
gulp.task('default', function() {
});
gulp.task('watch', function() {
gulp.watch('resources/**', ['default']);
elixir(function(mix) {
//Standard elixir code
});
});
Do note typing $ gulp in cli won't do anything anymore, unless you define something in the default task. $ gulp watch will work as always though.
I have no idea if this works without first requiring the dependency in package.json, but give it a try :)
Is there actually a Jade template engine for Laravel5?
Jade code would be much easier to develop with, and - it would produce a compact HTML code.
I am new to Laravel since today, figuring out the same question you have.
I think there are two different approches:
Compiling via build tools
First you could use npm, gulp and elixir - witch both come with Laravel.
Therefore you have to have npm and gulp installed (I assume you already have).
Use the laravel-elixir-jade module via
npm i --save-dev laravel-elixir-jade
After adding a couple of lines in your gulpfile you can run the default task via
gulp
Here is an example of an elixir function inside the gulpfile.js
var elixir = require('laravel-elixir');
require('laravel-elixir-jade');
elixir(function(mix) {
mix.less('app.less')
.jade({
baseDir: './resources',
blade: true,
dest: '/views/',
pretty: true,
search: '**/*.jade',
src: '/jade/'
});
});
Dont forget the require('laravel-elixir-jade'); at the beginning.
Compiling at server-side
You also have the possibility to let the PHP-Server render your jade files while rendering the page. I have created a package called mhochm/laravel-jadephp could be the right module for you.
I promise:
Create views as always but in Jade syntax
Require this package with composer:
composer require mhochm/laravel-jadephp
Add the ServiceProvider to the providers array in config/app.php:
'mhochm\LaravelJadePHP\LaravelJadePHPServiceProvider',
I hope this will help you :)
Moses