Trying to build LESS (less css) using a build script with nodeJS - css

We are using NodeJS to build our project. We have integrated LESS CSS as a part of the project. We are attempting to keep our build clean and would like to be able to call the lessc command (or something comparable) in order to build our LESS files.
The LESS documentation isn't very in depth, but wanted to reach out to the community to find a solution. Google has not be too helpful to me on this topic.
We have a build.sh file, that calls various other build.js files (in respective directories). How can I run LESSC to compile my LESS files?

Using node.js
var less = require('less')
,fs = require('fs');
fs.readFile('style.less',function(error,data){
data = data.toString();
less.render(data, function (e, css) {
fs.writeFile('style.css', css, function(err){
console.log('done');
});
});
});

Few years later ... less#3.9.0 returns output as:
{
css: 'rendered css',
imports: ['source.css']
}
Updated code can look like this:
const outputFile = 'style-iso.css';
const data = `.bootstrap-iso {
#import (less) "style.css";
} `;
less.render(data, { strictMath: true }).then(
output => {
fs.writeFile(outputFile, output.css, err => {
if (err) {
throw err;
}
console.log(`${outputFile} saved!`);
});
},
err => {
console.error(err);
});
Tip
strictMath: true
is necessary if you want to render bootstrap.css

Related

Embed current build time into humans.txt file with nextjs

Placing a humans.txt file into nextjs' /public folder works fine for a static file.
However I'd like to annotate the file with the date of the latest page build (when next build is called). So I created pages/humans.txt.tsx which renders a string that also contains the build time static date:
export default function Test({ buildTime }) {
return `Hello ${buildTime}`
}
export async function getStaticProps() {
return {
props: {
buildTime: new Date().toISOString()
}
}
}
I tried to customize pages/_document.js but even with everything stripped down (for testing) it still renders the doctype and one div with my text in it.
class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
ctx.renderPage = (props) => {
return {
html: "text",
head: null,
}
}
// Run the parent `getInitialProps`, it now includes the custom `renderPage`
const initialProps = await Document.getInitialProps(ctx)
return initialProps
}
render() {
return <Main/>
}
}
Output:
<!DOCTYPE html><div id="__next">text</div>
Returning just string from my documents render instead of <Main/> still renders the doctype and also causes a warning, since render should return an Element.
So I am out of ideas and might resort to using a prebuild script in package.json prebuild: sed ./pages/humans.txt... to replace a marker in the file with the system date and pipe it to public/humans.txt.
Here is an interesting runtime alternative:
Rewriting /humans.txt to /api/humans
You can use the following rule:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/humans.txt',
destination: '/api/humans',
},
]
},
}
Check the Rewrites docs here
Writing /api/humans
Now you can use any response in your API. However, make sure you are caching it:
// /pages/api/humans.js
export default function handler(req, res) {
res.setHeader('Cache-control', 's-maxage=6000, stale-while-revalidate=30')
res.setHeader('Content-type', 'text/plain')
res.status(200).end('example')
}
Check the API routes docs here

Solution for compiling SCSS and deploying to remote server

We are in need of a solution to compile SCSS and deploy to a remote server.
We have tried using both Grunt and Gulp setups but it appears that the FTP plugins for both are no longer compatible with newer versions of Grunt/Gulp.
We have also tried WebPack today which we like, but we're not sure how to deploy the compiled files.
We are needing to do it this way as it takes too long to download a copy of a clients site, make a small style change locally and reupload. We do want the benefits of using sass therefore we need a local solution to compile our styles and then deploy them to a specified folder on the server.
Our ideal workflow would be to make a change to a scss file (JS in the near future), a background task would see the change, compile it to css and another tasks would see that and deploy it to the correct remote folder.
Any ideas?
Thanks,
Neil
A small example of how you can recompile scss to css and upload to the server via ftp
Folder structure below and the normal call to node indes.js and that's it ;)
.
├── index.js
├── output.css
├── package.json
├── style.scss
└── yarn.lock
const fs = require('fs');
const sass = require('node-sass');
const ftp = require("basic-ftp")
const pathTotheFile = './output.css';
// compile scss
sass.render({
file: __dirname + './style.scss',
outputStyle: 'compressed',
outFile: __dirname + pathTotheFile,
// sourceMap: true,
}, function (error, result) {
if (error) {
console.log(error.status);
console.log(error.column);
console.log(error.message);
console.log(error.line);
} else {
console.log(result.stats);
fs.writeFile(pathTotheFile, result.css, function (err) {
if (!err) {
uploadCSStoServer();
}
})
}
});
// copy file to server
async function uploadCSStoServer() {
const client = new ftp.Client()
client.ftp.verbose = true
try {
await client.access({
host: "myftpserver.com",
user: "very",
password: "password",
secure: true
})
console.log(await client.list())
await client.uploadFrom("README.md", "README_FTP.md")
// await client.downloadTo("README_COPY.md", "README_FTP.md")
}
catch (err) {
console.log(err)
}
client.close()
}

Get which program is generated in meteor by babel

How can I know in babel plugin whether files currently transpiled by babel are transpiled for server or client/browser package?
Meteor recently implemented option caller available in babel 7. To use it and access information in plugin, one can access Babel.caller poperty like this:
let caller;
module.exports = function(Babel) {
Babel.caller(function(c) {
caller = { ...c };
});
return {
visitor: {
BlockStatement(){
console.log(caller); // logs e.g. {name: "meteor", arch: "web.browser.legacy"}
}
}
};
};

Getting a possible leak using gulp watch, tasks take longer each time

I'm using gulp to compile and minify my SASS in an ASP.NET5 website to use as a CDN. I've written a watcher that watches my *.scss files, it then uses dependencies to compile the scss and then concat/minify it into one style.min.css.
The issue I'm having is that the longer the project is open, or at least with each sequential run of the gulp tasks, they get considerably longer to the point where I had only been developing for about 20 minutes, and the compile task was taking 15+ second, and the minify was taking 25+ seconds. The very first run of each takes about 1 or 2 milliseconds so I'm really lost as to what's going on.
Here's my watcher:
gulp.task('Watch:Sass', function () {
watch(paths.cdn.sassLoc, { verbose: true }, function () {
gulp.start("Min:css");
});
});
Here is the Min:css task:
gulp.task("Min:css", ["Compile:Sass"], function () {
return gulp.src([paths.cdn.cssLoc, "!" + paths.cdnMinCssLoc + "**/*.*"])
.pipe(concat(paths.cdn.cssDest))
.pipe(cssmin())
.pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(gulp.dest("."));
});
And here is the Compile:Sass task that is being injected as a dependency:
gulp.task('Compile:Sass', function () {
gulp.src(paths.cdn.imagesLoc)
.pipe(gulp.dest(paths.webroot + '/css/min/images'));
return gulp.src(paths.cdn.sassLoc).pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(paths.cdn.sassDest));
});
Could it be because of my use of returns?
Any help would be greatly appreciated as I have to restart Visual Studio every half hour or so which gets extremely frustrating!
I'm sure I've included everything relevant, but please ask if you require any more info.
In this case it was in fact my return statements that were in the wrong place.
In order to fix the issue, I had to take off the return on the gulp.src(...) and I had to add a return true to the end of the Compile:Sass gulp task. I also took the return off of the Min:Css task completely and now my compile task takes ~1.5ms and my min task takes ~600us.
Here's the final Compile:Sass task:
gulp.task('Compile:Sass', function () {
gulp.src(paths.cdn.imagesLoc)
.pipe(gulp.dest(paths.webroot + '/css/min/images'));
gulp.src(paths.cdn.sassLoc).pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(paths.cdn.sassDest));
return true;
});
Matt, you have a concat on one of your "Min:css" task pipes.
gulp.task("Min:css", ["Compile:Sass"], function () {
return gulp.src([paths.cdn.cssLoc, "!" + paths.cdnMinCssLoc + "**/*.*"])
.pipe(concat(paths.cdn.cssDest))
...
...
.pipe(gulp.dest("."));
});
Make sure that you are not infinitely concatenating that same css over and over and over again. I can't tell what your paths.cdn.cssLoc points to. That would account for longer and longer processing time. You can call that a leak if you want.

passing grunt parameters from one task to another

I'm trying to pass the configuration values returned from the server(zookeeper) into compass (cdnHost, environment, etc) and seem to be having a hard time using the right approach.
I looked at ways to pass around args from one task to another on this page as a starting point
http://gruntjs.com/frequently-asked-questions#how-can-i-share-parameters-across-multiple-tasks
module.exports = function(grunt) {
grunt.initConfig({
compass: {
dist: {
//options: grunt.option('foo')
//options: global.bar
options: grunt.config.get('baz')
}
},
...
grunt.registerTask('compassWithConfig', 'Run compass with external async config loaded first', function () {
var done = this.async();
someZookeeperConfig( function () {
// some global.CONFIG object from zookeeper
var config = CONFIG;
// try grunt.option
grunt.option('foo', config);
// try config setting
grunt.config.set('bar', config);
// try global
global['baz'] = config;
done(true);
});
});
...
grunt.registerTask('default', ['clean', 'compassWithConfig', 'compass']);
I also tried calling the compass task directly, and it made no difference.
grunt.task.run('compass');
Any insights would be greatly appreciated. (e.g. way to use initConfig and have the value be available).
Thanks
When you write:
grunt.initConfig({
compass: {
dist: {
options: grunt.config.get('baz')
}
}
... grunt.config is called right away, and returns the value of baz as it is right now. Altering it (later) in another task simply won't get picked-up.
How to solve that?
#1: update compass.dist.options instead of updating baz
grunt.registerTask('compassWithConfig', 'Run compass with external async config loaded first', function () {
var done = this.async();
someZookeeperConfig( function () {
// some global.CONFIG object from zookeeper
var config = CONFIG;
grunt.config.set('compass.dist.options', config);
done();
});
});
Now, running task compassWithConfig first, then task compass will get the result you expect.
#2: wrap-up compass task execution in order to abstract away config mapping
grunt.registerTask('wrappedCompass', '', function () {
grunt.config.set('compass.dist.options', grunt.config.get('baz'));
grunt.task.run('compass');
});
// Then, you can manipulate 'baz' without knowing how it needs to be mapped for compass
grunt.registerTask('globalConfigurator', '', function () {
var done = this.async();
someZookeeperConfig( function () {
// some global.CONFIG object from zookeeper
var config = CONFIG;
grunt.config.set('baz', config);
done();
});
});
Finally, running task globalConfigurator then wrappedCompass will get you to the result.

Resources