How to solve gulp image copy issue on build? - image

Problem - copied images end up with size 0 x 0 px.
In my gulpfile.js I copy images from the app directory to the dist directory, which works well. Here's a simplified version of the task:
gulp.task('html-deploy', function() {
return gulp.src([
'app/img/**/*',
'app/**/*.html'
],
{
base: 'app'
}
)
.pipe(gulp.dest('dist'))
});
My file structure looks like this:
/app
index.html
/img
image1.png
image2.png
Everything copies over well and nice, however the images don't display in the browser, even though filepaths are correct.
The weird thing is when I locate the images directly in Finder (osx) I can't view them there either, although the filesizes and read/write values are correct too.
This is probably because the copied images end up being 0x0 px in size. Why is this happening?

Was facing the same issue with ionic 2 application.
I included gulp task
gulp.task('images', function() {
return gulp.src('app/images/**/*')
.pipe(gulp.dest('www/build/images'));
});
called it from other build tasks are called (gulp task build)
and changed my image reference to refer from build folder:
<img src="build/images/mylogo.png" height="50px" width="50px">
Hope it helps someone!

This is kind of an answer to my own question - at least it fixed the problem.
Instead of directly copying the images I copy them via gulp-imagemin, and voilĂ !
var gulp = require('gulp');
var imagemin = require('gulp-imagemin')
var del = require('del')
// Minify and copy new images to dist
gulp.task('imagemin', ['clean'], function() {
return gulp.src('app/img/**/*')
.pipe(changed('dist/img'))
.pipe(imagemin())
.pipe(gulp.dest('dist/img'))
})

Related

Laravel-mix versioning when uploaded in S3 thinks in previous hash

With using webpack-s3-plugin npm package, I'm saving my laravel-mix compiled & versioned files into S3 (for cdn purposes).
Bare in mind, this was working until yesterday.
let webpackPlugins = [];
if (mix.inProduction() && process.env.UPLOAD_S3) {
webpackPlugins = [
new s3Plugin({
include: /.*\.(css|js)$/,
s3Options: {
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_SECRET,
region: process.env.AWS_REGION,
},
s3UploadOptions: {
Bucket: process.env.ASSETS_S3_BUCKET,
CacheControl: 'public, max-age=31536000'
},
basePath: 'assets/' + process.env.APP_ENV,
directory: 'public'
})
]
}
mix.scripts([ // I also tried '.combine'
'resources/js/vendor/vendor/jquery.slimscroll.js',
'resources/js/vendor/custom/theme-app.js',
], 'public/js/scripts.js')
// Other bundling stuff
.js([...].version()
mix.webpackConfig({
plugins: webpackPlugins
});
Now, S3's eTag doesn't match to mix-manifest.json hash. And, when I visit the page, it fetches 1 version behind, not the latest uploaded but exactly 1 previous version. However, when I check the 'updated date' on S3, it's correct. Nevertheless, it's exactly one version behind.
What I suspect is it is uploading to s3 before the bundling is completely done; however I am not sure. What am I missing here?
I used this guide if you want to know the laravel side in detail.
After diving around the S3 plugin source, I am fairly confident this is caused by the hook used to trigger the S3 upload. I don't know enough about webpack plugins to give a full description of this, but I have made an educated guess at what is causing the issue and my proposed fix seems to have sorted the issue.
The author of the plugin has accepted my pull request and the fix is currently awaiting release.
If you need a fix in the meantime, then you can do it like so (note, this is very dirty and should be treated as temporary):
Browse to your node_modules folder
Locate the folder named webpack-s3-plugin
Copy the file dist/s3_plugin.js
Paste somewhere in your project
Open the file and locate the line t.hooks.afterEmit.tapPromise
Replace with t.hooks.done.tapPromise
In your webpack.mix.js file, change the require('webpack-s3-plugin') to point to your javascript file
Just to reiterate, this is a temporary fix until the latest version of the plugin is released.

Gulp sass watching even the imports and run the main parent

I have this gulp task:
gulp.task('css', function() {
return gulp.src( [CONFIG.css.source + '/**/*.scss'].concat(CONFIG.css.ignore) )
.pipe( watch([CONFIG.css.source + '/**/*.scss'].concat(CONFIG.css.ignore)) )
.pipe( sass({errLogToConsole: true}) )
.pipe( gulp.dest(CONFIG.css.dest) )
});
With this task, I watch the .scss files and apply the sass on them. The problem is that when I use #import partial.scss. These partials are not watched, so I have everytime to save the partial file and then save even the main style.scss file (who calls the import), in order to start the task.
How can I watch even the imports, without have to save both import and importer scss files ?
To make it simple, let's say I have a file style.scss that imports partials/partial.scss. When I edit and save the partial, only the task on style.scss should run.
Notes:
CONFIG.css.ignore is the path to the partials folder (in this way, they will not be directly watched and saved in the wrong folder), but this also causes the problem that the partials are not watched..
I suggest / use a slightly different approach. I have a sepate task to kick off watchers, e.g.:
var pathToAllScssIncludingPartials = '/**/*.scss';
gulp.task('watchStyles', [], function() {
gulp.watch(pathToAllScssIncludingPartials, ['css']);
});
This kicks off 'css' whenever an input file changes. No need do any watch stuff inside the css task anymore.

Laravel elixir compile multiple less files

I have this two files in resources/assets/less folder style.less and admin/style.less. I want to compile this files to diffrent paths as the following:
style.less compiled to public/css/
and the other one compiled to public/admin/styles/
this is What i did in the gulpfile.js
elixir(function(mix) {
mix.less('style.less', 'public/css/');
mix.less('admin/style.less', 'public/admin/styles/');
});
but this compile only one file.
What is the problem and how can i fix this issue?
I have a project that compiles two different less files to two different css files.
The only difference that I see is that I specify the full destination path including the file name.
So, for your case, it will be:
elixir(function(mix) {
mix.less('style.less', 'public/css/style.css')
.less('admin/style.less', 'public/admin/styles/style.css');
});
I have not got the answer for this yet. But have tried some alternatives, thought will share.
I was thinking we can do like below
elixir(function(mix) {
mix.less('style.less', 'public/css/')
.less('admin/style.less', 'public/admin/styles/');
});
But according to the documentation we can't make multiple call to sass or less method. So it is only compiling the latest less file (which in this case admin/style.css).
We can do like this
elixir(function(mix) {
mix.less(['style.less', 'admin/style2.less'], 'public/css/');
});
but this will compile both into the same folder.
Hoping to know, how can we do it to different folders.
I tried copying the second file into a separate folder, but that also doesn't work
elixir(function(mix) {
mix.less(['style.less', 'admin/style2.less'], 'public/css/')
.copy('public/css/style2.css', 'public/admin/style.css');
});
Probably this is because each requests are async and when the copy is getting called, that time the style2.css is not ready yet.
mix.less('resources/assets/less/app.scss', 'public/css').
less('resources/assets/less/admin/style.less', 'public/admin/styles');

Laravel elixir - don't generate map files

The question is - how to force Laravel Elixir not to generate map files?
At the moment if I run gulp I will have generated app.css and app.css.map file. I don't know what for is this app.css.map file but I think it's not necessary for me at the moment. Question is - how to force gulp not to generate this file?
At the moment my gulpfile.js looks like this:
var elixir = require('laravel-elixir');
elixir(function(mix) {
mix.sass('app.scss', 'public/css/app.css');
});
This is no longer achievable via elixir.extend() syntax, instead the official documentation now suggests to use this:
elixir.config.sourcemaps = false;
Starting from Elixir 3.0 you can put a JSON object that will override the default configuration in elixir.json:
{
"sourcemaps": false
}
.map files are called source maps. Their purpose is to map the contents of a concatenated, minified file to it's original files to make debugging easier.
You can disable them by changing elixirs config using extend() in your gulpfile
elixir.extend('sourcemaps', false);
Note that source maps are disabled by default when running in production.

Combining Multiple SASS files into one SASS file

Does anyone know if there is a way to combine multiple SASS/SCSS files into one SASS/SCSS file. I do mean "into one SASS/SCSS" and not into a CSS file.
For example, I have 3 scss files:
app.scss
base.scss
layout.scss
The app.scss file contains 2 imports to base.scss and layout.scss.
I would like to beable to generate 1 SCSS file that basically concatenates the files and does not process the sass.
It's fairly difficult to search for as everything that gets return is to do with combining into CSS.
Why would I want to do this? Basically, I'd like to easily reference a set of SCSS files from within a codepen (other online code editor).
Thanks
I analyze all files by the mask, find all imports inside and concatenate into one file. So I don't need one entry point
npm install -D bundle-scss
"script": {
"postbuild": "npm run themes",
"themes": "bundle-scss -m \"./src/**/*.theme.scss\" -d \"./dist/themes.scss\""
}
scss-bundle solves this problem
https://github.com/reactway/scss-bundle
Caution: Does not support newer module based imports. Issue #90
You could modify this for javascript. Kept it in typescript as I am currently solving this issue on my own (angular 6 library), and ran into this question.
According to the docs, angular material uses this implementation.
import * as path from 'path';
import { Bundler } from 'scss-bundle';
import * as fs from 'fs';
(async () => {
// Absolute project directory path.
// Assuming all of your scss files are in `./projects/my-library/src/styles`
const projectDirectory = path.resolve(__dirname, './projects/my-library/src/styles');
const bundler = new Bundler(undefined, projectDirectory);
// Relative file path to project directory path.
// The name of your file here would be `app.scss`
// Kept this here if anyone runs into this answer and wants to do this with the new angular 6 library.
const { found, bundledContent } = await bundler.Bundle('./_all-theme.scss');
if (found && bundledContent) {
// where you want to save the file, and what you would like it to be called.
const location = path.resolve(__dirname, '_theming.scss');
fs.writeFileSync(location, bundledContent);
}
})();

Resources