I am attempting to start using Bourbon and Neat Sass libraries in my project. I want to compile Sass with Gulp. This is a simple styles task setup that I've found in one of the tutorials:
var gulp = require('gulp'),
sass = require('gulp-sass'),
neat = require('node-neat').includePaths;
var paths = {
scss: './assets/styles/*.scss'
};
gulp.task('styles', function () {
return gulp.src(paths.scss)
.pipe(sass({
includePaths: ['styles'].concat(neat)
}))
.pipe(gulp.dest('./dist/styles'));
});
gulp.task('default', function () {
gulp.start('styles');
});
Then in the main .scss file I place the imports:
#import "bourbon";
#import "base/base";
#import "neat";
This task executes correctly.
What puzzles me here is what includePaths does exactly?
Base on the example above, can somebody explain to me what includePath's role is?
The SASS compiler uses each path in loadPaths when resolving SASS #imports.
loadPaths: ['styles/foo', 'styles/bar']
#import "x"; // found via ./styles/foo/_x.scss
#import "y"; // found via ./styles/bar/_y.scss
Note that the compiler resolves each #import by considering each path in loadPaths from left-to-right (similar to $PATH in a UNIX environment). An example scenario could be:
loadPaths: ['styles/i', 'styles/ii', 'styles/iii', 'styles/iv']
#import "x"; // no file at ./styles/i/_x.scss
// no file at ./styles/ii/_x.scss
// found a file at ./styles/iii/_x.scss ...
// ... this file will be used as the import
// ... terminate lookup
// the file ./styles/iv/_x.scss will be ignored
There was no _x.scss file in styles/i, so it moved on to look inside styles/ii. Eventually it found an _x.scss file in styles/iii and finished the lookup. It looks at each folder in loadPaths starting from the first element in the array and moving right. After attempting all paths, if we can't find the file, then we declare that this #import statement is invalid.
Load paths is useful if you have a external library (like bournon/neat).
The external library is large and will use lots of #import statements. However they won't match your project folder structure and so won't resolve. However, you can add an extra folders to the loadPaths so that the #imports inside the external library do resolve.
includePaths
Type: Array Default: []
An array of paths that libsass can look in to attempt to resolve your #import declarations. When using data, it is recommended that you use this.
in sass, you can orginize your sass files in multiple folders, but you want your main.sass to be able to import them when it compiles, so you can specify the includePaths, so that sass knows where to find the #import sass file, here you use node-neat, if you want to import some styles from it, by default, sass don't know where to look, so you need to tell sass where to find the file to import
Related
I have a script that does some analysis on my source files and a part of that analysis is to require the file. Some of the files are in JSX format however and node does not understand this by default.
Is it possible to make it so that a file that looks like this:
function MyModule () {
return <div>hello</div>
}
module.exports = MyModule
is possible to require through require('./my-module')?
Use JSX as a template engine in Node
NPM Package : https://www.npmjs.com/package/jsx-node
To be able to simply require .jsx files, you need to tell Node what to do with them. Running the following code makes you able to require('./SomeFile.jsx'):
require('jsx-node').install({
replace: {
preact: 'jsx-node',
}
});
Warning:
This module is still in a very early phase. Any production use should be approached with caution.
For more Detail visit Link.
I'm writing a module for a react app that needs to be included on both the backend and frontend.
At some point in my code, I'm requiring some svg file (for which I use a browserify module, but this has nothing to do with the question).
For example I have in my ./src/js/components/tools/svg.js the following bit of code:
// ...
var BACKEND = /* code to detect if this is running on browser or on node */;
var svg;
if ( BACKEND ) {
svg = require("./../../../icon/" + this.props.icon + ".svg");
} else {
svg = require("./src/icon/" + this.props.icon + ".svg");
}
// ....
I use browserify's require option to require all the svg files at bundle-time:
browserify({
paths: ['./src/icon'],
})
.transform(/* svg tansformer */)
.require(glob.sync("./src/icon/*.svg")) // <-- svg's get added here
.add("./src/main.js"); // main entry point
However this conflicts with how node resolves the filenames. It cannot find ./src/icon/ from ./src/js/components/tools/svg.js.
This is why I have to guard the require with the BACKEN clause. This breaks my eyes though and I would like to just be able to write:
var svg = require('./src/icon/' + this.props.icon + '.svg');
I've tried two things so far:
fix node to find ./src/icon
I can use export NODE_PATH=`cwd` to allow node to look for src/icon from ./. This allows me to write:
var svg = require('src/icon/' + this.props.icon + '.svg');
in the backend. But, since browserify only accepts paths that start with ./ (thus, ignoring src/icon) this will not resolve on the frontend.
fix browserify to use ../../../icon/
Haven't got this to work either because of the same reason: browserify only accepts paths that start with ./.
It's considered bad practice doing conditional requires when using Browserify because it can't evaluate the code at "compile time" and will always attempt to load all the files.
To load different files in the browser environment than on node is easy:
Add a "browser" field to your package.json that points to the browser main file. Use "main" for the node main file. Then just require the module.
You can do the same thing with sub folders within your project. Just add a package.json file with "private": true and both, the main and the browser properties and require the folder path.
I feel like this must be so obvious but it's escaping me.
I'd like to run requirejs's r.js compilation from a node module instead of from the command line, and every bit of documentation I've seen just shows the command line option. Something like this is what I'm looking for:
var r = require('requirejs');
r('./build/common.js');
r('./build/app-main.js');
Let me explain the underlying motivation in case there's a better way to do it:
I've got a few different build.js files that I want to run r.js on (separate bundles for common dependencies and the main app). I'd like to wrap this up inside a gulpfile or gruntfile that runs both, and without putting all the r.js config in the actual grunt/gulp file like the grunt and gulp require.js plugins all seem to do. Leaving the r.js config in the separate build/*.js files would let us use grunt/gulp OR command line when we want to.
Any way to accomplish this?
Using the optimizer as a Node module is documented but it is not in the most evident place. This is the example that the documentation gives:
var requirejs = require('requirejs');
var config = {
baseUrl: '../appDir/scripts',
name: 'main',
out: '../build/main-built.js'
};
requirejs.optimize(config, function (buildResponse) {
//buildResponse is just a text output of the modules
//included. Load the built file for the contents.
//Use config.out to get the optimized file contents.
var contents = fs.readFileSync(config.out, 'utf8');
}, function(err) {
//optimization err callback
});
There are several Javascript files, organized in folders Scripts/folder1, Scripts/folder2, ...
With requirejs.config.baseUrl a folder is defined as the default, for example Scripts/folder1. Then in requirejs.config.paths some files are addressed with just the filename, and some are addressed with a relative path (like ../folder2/blabla).
When coding the Typescipt file folder2/blabla.ts we need the module "math" from folder1. So we write
import MOD1 = module("../folder1/math");
Regarding Typescript, anything is fine with that. It can find the module. However, with requirejs there is a problem. It does not know the module "../folder1/math", it only knows "math".
The problem seems to be that the import statement expects a filename, being adressed by starting from the current directory. However, this isn't the module id that requirejs knows about.
Using absolute paths anywhere, both in the requirejs configuration and the import statement in Typescript, solves the problem.
Am I doing this wrong? Or are absolute paths the way to go?
Specify a baseUrl to be equivalent to the root folder of your Typescript files:
require.config({
baseUrl: './scripts',
}
)
Then when you use relative paths starting from the scripts folder you can just do import like you normally do in typescript and requirejs will be using the same base path.
Update: This presentation should should answer all your url / using js from Typescript questions: http://www.youtube.com/watch?v=4AGQpv0MKsA with code : https://github.com/basarat/typescript-amd/blob/master/README.md
In you require configuration specify paths for each module. That should solve paths problem:
require.config({
paths: {
jquery: 'libs/jquery-1.7.1.min',
jqueryui: 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min'
// Other modules...
}
});
In a PhantomJS script I would like to load a custom module but it seems relative paths do not works in PhantomJS ?
script.js:
var foo = require('./script/lib/foo.js');
foo.bar('hello world');
phantom.exit();
foo.js:
exports.bar = function(text){
console.log(text);
}
According to fs.workingDirectory I am in the good directory
foo.js is not in the lookup path of phantomjs
Am I missing something ?
EDIT:
inject() is not revelant because I do not need to inject a JS to an HTML page but instead load my own module like require('fs') but with a relative path.
After a lot of time searching for the same thing, here is what I understood, though I might be wrong :
PhantomJS doesn't use Node's require, but its own require, so things are different
when providing a relative path to phantomjs's require, it is always interpreted as relative to the current working directory
PhantomJS doesn't implement node's __dirname, and as such there is no direct way to have the directory of your script
The solution I found least annoying :
if using phantomjs pure, without casperjs :
require(phantom.libraryPath + '/script/lib/foo.js')
if using casperjs :
var scriptName = fs.absolute( require("system").args[3] );
var scriptDirectory = scriptName.substring(0, scriptName.lastIndexOf('/'));
require(scriptDirectory + '/script/lib/foo.js')
To load your own module, the right way to do it is to use module.exports, like this: foo.js
function bar(text) {
console.log(text);
}
exports.bar = bar
And in script.js (which is executed with phantomjs script.js):
var foo = require('./script/lib/foo');
foo.bar('hello world');
phantom.exit();
My solution to load a resource file (like let's say a json file) within a phantomjs subfolder from a outer folder like in this structure:
├── consumer.js
├── assets
├── data.json
├── loader.js
Supposed that data.json must be load by the consumer module and that this module is called by somewhere else on this machine, outside the project root folder, the fs.workingDirectory will not work, since it will be the path of the caller file.
So to solve this, I did a simple loader module within the assets folder, where the files I want to load are:
(function() {
var loader = {
load : function(fileName) {
var res=require('./'+fileName);
return res;
}
}
module.exports=loader;
}).call(this);
I therefore call the loader module from the consumer module like
var loader=require('./data/loader');
var assets=loader.load('data.json');
and that's it.
NOTE. The require here is the phantomjs require not the node version, so it works a bit differently. In this case the data.json was a json array with no module.exports declaration. The array will be backed in the assets variable directly when calling the loader.load(fileName) method.
have you tried to use injectJs(filename)
excerpt form PhantomJS documentation:
Injects external script code from the specified file. If the file can
not be found in the current directory, libraryPath is used for
additional look up.
This function returns true if injection is successful, otherwise it
returns false.
Which PhantomJS version are you running? Support for user provided modules was added in 1.7.