I've recently switched from using Web Essentials to grunt-ts to compile my typescript files due to the flexibility of output. Part of the reason I switched is that I don't want all files compiled seperately, and I don't want to have all files compiled to a single file. I want a bit of both. Since I've recently started using grunt for a lot of tasks, I thought I might as well switch my TS build too.
Here's my gruntfile
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
dirs: {
distribution: 'script/dist',
ts_root: 'script/src',
ts_controllers: 'script/src/controllers'
},
ts: {
apprunner: {
src: ['<%= dirs.ts_root %>/main.ts'],
out: '<%= dirs.distribution %>/src/main.js',
options: {
target: 'es5'
}
},
controllers: {
src: ['<%= dirs.ts_controllers %>/*.ts'],
out: '<%= dirs.distribution %>/src/controllers.js'
options: {
target: 'es5'
}
}
}
});
grunt.loadNpmTasks('grunt-ts');
grunt.registerTask('default', ['ts']);
};
Inside the main.ts file, I have to reference one of the typescript files that, when compiled, makes up part of the controllers.js file.
So my main.js file I have the following:
/// <reference path="controllers/ExampleController.ts" />
var newExample = new wctApp.controllers.ExampleController();
Grunt compiles my controllers.js file fine:
var wctApp;
(function (wctApp) {
(function (controllers) {
var ExampleController = (function () {
function ExampleController() {
}
return ExampleController;
})();
controllers.ExampleController = ExampleController;
})(wctApp.controllers || (wctApp.controllers = {}));
var controllers = wctApp.controllers;
})(wctApp || (wctApp = {}));
But it compiles the same code inside the main.js file.
var wctApp;
(function (wctApp) {
(function (controllers) {
var ExampleController = (function () {
function ExampleController() {
}
return ExampleController;
})();
controllers.ExampleController = ExampleController;
})(wctApp.controllers || (wctApp.controllers = {}));
var controllers = wctApp.controllers;
})(wctApp || (wctApp = {}));
;
var newExample = new wctApp.controllers.ExampleController();
If I remove the reference from the main file, it won't build because it can't find ExampleController. How can I keep the reference to this file, but stop it from being compiled in the main.js file.
Don't use out. Because out merges all the TypeScript files into one. Instead use outDir (if you need to redirect to a different folder). Or better don't use anything (no out no outDir) and it will put the generated JS next to the file.
Related
I'm using gatsby-plugin-sass to include my sass files. I have a web-animations.sass file that imports _typography.sass. My _typography.sass has a font-face declaration like this:
#font-face
font-family: 'BrandonPrinted'
src: url(../../global/fonts/brandonprinted-one-webfont.eot)
src: url(../../global/fonts/brandonprinted-one-webfont.eot?#iefix) format('embedded-opentype'), url(../../global/fonts/brandonprinted-one-webfont.woff) format('woff'), url(/src/page-assets/global/fonts/brandonprinted-one-webfont.ttf) format('truetype')
When I run gatsby develop I get this error:
ERROR Failed to compile with 2 errors 19:51:15
These relative modules were not found:
* ../../global/fonts/brandonprinted-one-webfont.eot in ./~/css-loader!./~/sass-loader?{"plugins":[]}!./src/page-assets/work-ive-done/subpages/web-animations/styles/web-animations.sass
* ../../global/fonts/brandonprinted-one-webfont.woff in ./~/css-loader!./~/sass-loader?{"plugins":[]}!./src/page-assets/work-ive-done/subpages/web-animations/styles/web-animations.sass
It seems that the font url path is interpreted to be relative to web-animations.sassinstead of relative to _typography.sass because if I move web-animations.sass up two levels, then this error goes away.
Is there a way to have _typography.sass look for the font files relative to its own location?
Seems like this is resolved, but in case anyone runs across this in the future and wants an alternative solution I answered a similar question over here and included a repo with a deployed site demonstrating different ways of using static files with Sass.
I got this working by including the resolve-url-loader Webpack loader.
Here's my gatsby-node.js file:
"use strict";
var ExtractTextPlugin = require(`extract-text-webpack-plugin`);
var _require = require(`gatsby-1-config-css-modules`),
cssModulesConfig = _require.cssModulesConfig;
exports.modifyWebpackConfig = function (_ref, options) {
var config = _ref.config,
stage = _ref.stage;
var sassFiles = /\.s[ac]ss$/;
var sassModulesFiles = /\.module\.s[ac]ss$/;
options['sourceMap'] = 'sourceMap';
var sassLoader = `sass?${JSON.stringify(options)}`;
switch (stage) {
case `develop`:
{
config.loader(`sass`, {
test: sassFiles,
exclude: sassModulesFiles,
loaders: [`style`, `css`, 'resolve-url-loader', sassLoader]
});
return config;
}
case `build-css`:
{
config.loader(`sass`, {
test: sassFiles,
exclude: sassModulesFiles,
loader: ExtractTextPlugin.extract([`css?minimize`, 'resolve-url-loader', sassLoader])
});
config.loader(`sassModules`, {
test: sassModulesFiles,
loader: ExtractTextPlugin.extract(`style`, [cssModulesConfig(stage), 'resolve-url-loader', sassLoader])
});
return config;
}
case `develop-html`:
case `build-html`:
case `build-javascript`:
{
config.loader(`sass`, {
test: sassFiles,
exclude: sassModulesFiles,
loader: `null`
});
config.loader(`sassModules`, {
test: sassModulesFiles,
loader: ExtractTextPlugin.extract(`style`, [cssModulesConfig(stage), 'resolve-url-loader', sassLoader])
});
return config;
}
default:
{
return config;
}
}
};
I am having troubling running sass and minification together. Some times the minification task starts before the sass task has finished.
When I run the separately they work fine.
Here is my gulp file...
/// <binding />
"use strict";
var gulp = require("gulp"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
merge = require("merge-stream"),
del = require("del"),
bundleconfig = require("./bundleconfig.json"),
runSequence = require('run-sequence');
var sass = require('gulp-sass');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var webroot = "./wwwroot/";
var paths = {
scss: webroot + "sass/**/*.scss",
scssDest: webroot + "css/"
};
// 1. react
gulp.task('react', function () {
return browserify({ entries: './wwwroot/clientapp/root', extensions: ['.jsx', '.js'], debug: true })
.transform('babelify', { presets: ['es2015', 'react'] })
.bundle()
.pipe(source('index.js'))
.pipe(gulp.dest('./wwwroot/'));
});
// 2. sass
gulp.task('compile:sass', function () {
gulp.src(paths.scss)
.pipe(sass())
.pipe(gulp.dest(paths.scssDest));
});
gulp.task("sass", ["compile:sass"]);
function getBundles(regexPattern) {
return bundleconfig.filter(function (bundle) {
return regexPattern.test(bundle.outputFileName);
});
}
gulp.task("css", function () {
var tasks = getBundles(/\.css$/).map(function (bundle) {
return gulp.src(bundle.inputFiles, { base: "." })
.pipe(concat(bundle.outputFileName))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
return merge(tasks);
});
gulp.task("clean", function () {
return del(['wwwroot/css/*', 'wwwroot/index.js']);
});
gulp.task("default", ["clean", "sass", "react", "css"]);
It looks like you are assuming that these tasks are run in series:
gulp.task("default", ["clean", "sass", "react", "css"]);
They do not, from gulp.task documentation:
Note: The tasks will run in parallel (all at once), so don't assume that the tasks will start/finish in order.
There are a number of ways to fix that and there should be a few questions here on the subject.
You can use run-sequence, use gulp4.0 which has series and parallel functions (but is still technically in beta) or make some task like your 'react' task dependent on the 'sass' and 'css" tasks having finished.
So try :
gulp.task('react', ['css'], function () { ...
gulp.task("css", ['sass'], function () { ...
gulp.task('compile:sass', ['clean'], function () { ...
and now simply
gulp.task("default", ["react"]);
will fire them off in the correct order.
Although I suppose 'clean' doesn't necessarily have to run first. run-sequence does help to make the order of things much more obvious. If you can I would suggest looking into gulp4.
I have the following in my gulpfile.js:
var sass_paths = [
'./httpdocs-site1/media/sass/**/*.scss',
'./httpdocs-site2/media/sass/**/*.scss',
'./httpdocs-site3/media/sass/**/*.scss'
];
gulp.task('sass', function() {
return gulp.src(sass_paths)
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefixer('last 4 version'))
.pipe(minifyCSS({keepBreaks:true}))
.pipe(rename({ suffix: '.min'}))
.pipe(gulp.dest(???));
});
I'm wanting to output my minified css files to the following paths:
./httpdocs-site1/media/css
./httpdocs-site2/media/css
./httpdocs-site3/media/css
Am I misunderstanding how to use sources/destinations? Or am I trying to accomplish too much in a single task?
Edit: Updated output paths to corresponding site directories.
I guess that the running tasks per folder recipe may help.
Update
Following the ideas in the recipe, and oversimplifying your sample just to give the idea, this can be a solution:
var gulp = require('gulp'),
path = require('path'),
merge = require('merge-stream');
var folders = ['httpdocs-site1', 'httpdocs-site2', 'httpdocs-site3'];
gulp.task('default', function(){
var tasks = folders.map(function(element){
return gulp.src(element + '/media/sass/**/*.scss', {base: element + '/media/sass'})
// ... other steps ...
.pipe(gulp.dest(element + '/media/css'));
});
return merge(tasks);
});
you are going to want to use merge streams if you would like to use multiple srcs but you can have multiple destinations inside of the same one. Here is an example.
var merge = require('merge-stream');
gulp.task('sass', function() {
var firstPath = gulp.src(sass_paths[0])
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefixer('last 4 version'))
.pipe(minifyCSS({keepBreaks:true}))
.pipe(rename({ suffix: '.min'}))
.pipe(gulp.dest('./httpdocs-site1/media/css'))
.pipe(gulp.dest('./httpdocs-site2/media/css'));
var secondPath = gulp.src(sass_paths[1])
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefixer('last 4 version'))
.pipe(minifyCSS({keepBreaks:true}))
.pipe(rename({ suffix: '.min'}))
.pipe(gulp.dest('./httpdocs-site1/media/css'))
.pipe(gulp.dest('./httpdocs-site2/media/css'));
return merge(firstPath, secondPath);
});
I assumed you wanted different paths piped here so there is site1 and site2, but you can do this to as many places as needed. Also you can specify a dest prior to any of the steps if, for example, you wanted to have one dest that had the .min file and one that didn't.
You can use gulp-rename to modify where files will be written.
gulp.task('sass', function() {
return gulp.src(sass_paths, { base: '.' })
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefixer('last 4 version'))
.pipe(minifyCSS({keepBreaks:true}))
.pipe(rename(function(path) {
path.dirname = path.dirname.replace('/sass', '/css');
path.extname = '.min.css';
}))
.pipe(gulp.dest('.'));
});
Important bit: use base option in gulp.src.
For the ones that ask themselves how can they deal with common/specifics css files (works the same for scripts), here is a possible output to tackle this problem :
var gulp = require('gulp');
var concat = require('gulp-concat');
var css = require('gulp-clean-css');
var sheets = [
{ src : 'public/css/home/*', name : 'home.min', dest : 'public/css/compressed' },
{ src : 'public/css/about/*', name : 'about.min', dest : 'public/css/compressed' }
];
var common = {
'materialize' : 'public/assets/materialize/css/materialize.css'
};
gulp.task('css', function() {
sheets.map(function(file) {
return gulp.src([
common.materialize,
file.src + '.css',
file.src + '.scss',
file.src + '.less'
])
.pipe( concat(file.name + '.css') )
.pipe( css() )
.pipe( gulp.dest(file.dest) )
});
});
All you have to do now is to add your sheets as the object notation is constructed.
If you have additionnal commons scripts, you can map them by name on the object common, then add them after materialize for this example, but before the file.src + '.css' as you may want to override the common files with your customs files.
Note that in the src attribute you can also put path like this :
'public/css/**/*.css'
to scope an entire descendence.
I had success without needing anything extra, a solution very similar to Anwar Nairi's
const p = {
dashboard: {
css: {
orig: ['public/dashboard/scss/style.scss', 'public/dashboard/styles/*.css'],
dest: 'public/dashboard/css/',
},
},
public: {
css: {
orig: ['public/styles/custom.scss', 'public/styles/*.css'],
dest: 'public/css/',
},
js: {
orig: ['public/javascript/*.js'],
dest: 'public/js/',
},
},
};
gulp.task('default', function(done) {
Object.keys(p).forEach(val => {
// 'val' will go two rounds, as 'dashboard' and as 'public'
return gulp
.src(p[val].css.orig)
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(autoPrefixer())
.pipe(cssComb())
.pipe(cmq({ log: true }))
.pipe(concat('main.css'))
.pipe(cleanCss())
.pipe(sourcemaps.write())
.pipe(gulp.dest(p[val].css.dest))
.pipe(reload({ stream: true }));
});
done(); // <-- to avoid async problems using gulp 4
});
Multiple sources with multiple destinations on gulp without using any extra plugins just doing concatenation on each js and css. Below code works for me. Please try it out.
const gulp = require('gulp');
const concat = require('gulp-concat');
function task(done) {
var theme = {
minifiedCss: {
common: {
src : ['./app/css/**/*.min.css', '!./app/css/semantic.min.css'],
name : 'minified-bundle.css',
dest : './web/bundles/css/'
}
},
themeCss:{
common: {
src : ['./app/css/style.css', './app/css/responsive.css'],
name : 'theme-bundle.css',
dest : './web/bundles/css/'
}
},
themeJs: {
common: {
src: ['./app/js/jquery-2.1.1.js', './app/js/bootstrap.js'],
name: 'theme-bundle.js',
dest: './web/_themes/js/'
}
}
}
Object.keys(theme).map(function(key, index) {
return gulp.src(theme[key].common.src)
.pipe( concat(theme[key].common.name) )
.pipe(gulp.dest(theme[key].common.dest));
});
done();
}
exports.task = task;
Using gulp-if helps me a lot.
The gulp-if first argument. is the gulp-match second argument condition
gulp-if can be found in gulp-if
import {task, src, dest} from 'gulp';
import VinylFile = require("vinyl");
const gulpif = require('gulp-if');
src(['foo/*/**/*.md', 'bar/*.md'])
.pipe(gulpif((file: VinylFile) => /foo\/$/.test(file.base), dest('dist/docs/overview')))
.pipe(gulpif((file: VinylFile) => /bar\/$/.test(file.base), dest('dist/docs/guides')))
});
I think we should create 1 temporary folder for containing all these files. Then gulp.src point to this folder
The destination will have the same directory structure as the source.
I am new to NodeJs and Grunt, and I want to ask a question that is probably already answered, but I either couldn't understand solution, or couldn't find it.
So, I have www folder with many subfolders with projects. Every project has same folders inside,
--css/style.css
--sass/style.scss
--js/script.js + /1.js + /2.js
--build/script.js
--build/style.css
My Gruntfile.js with grunt is at www folder, and my grunt concat, goes something like this:
grunt.initConfig({
concat: {
dist: {
src: ['**/js/1.js', '**/js/2.js', '**/js/script.js'],
dest: '**/build/script.js'
},
},
});
Now, you can probably see the problem, I get error "Can't create directory C/wamp/www/** ..., and I need to be able to select same folder as where it found js (and later css and other tasks as well).
The most simple solution is needed, and I plan to use concat, watch, uglify, sass (solution for sass is welcome as well).
I am apologizing if this question is repeated, but I can't find an answer.
You cannot use a globbing pattern for your dest value, as globbing is for matching patterns. You will need a separate src -> dest mapping for each project subfolder. There are a few ways to do this, but I will use the Files Object Format. Assuming project subfolders named proj1/ and proj2/, the configuration would look like the following:
concat: {
dist: {
files: {
'proj1/build/script.js': 'proj1/js/*.js',
'proj2/build/script.js': 'proj2/js/*.js'
}
}
}
If you are going to keep adding project subfolders, it might make sense to build the concat configuration dynamically:
var project_dirs = ['proj1', 'proj2'];
var concat_config = {
dist: {}
};
concat_config.dist.files = project_dirs.reduce(function (memo, dir) {
var src = dir + '/js/*.js';
var dest = dir + '/build/script.js';
memo[dest] = src;
return memo;
}, {});
grunt.initConfig({
concat: concat_config
});
First
Concat and uglify your js:
concat.dev = {
files: {
"public/myapp.development.js": [
"with-bootstrap/public/js/vendor", "with-bootstrap/public/js/**/*.js"
]
}
};
//Uglify ===============================
config.uglify = {
dist: {
options: {
sourceMap: "public/myapp.production.js.map"
},
files: {
"public/myapp.production.js": ["public/myapp.development.js"]
}
}
}
and your sass:
//Sass ===============================
var sass;
config.sass = sass = {};
//distribution
sass.dist = {
options: {
style: "compressed",
noCache: true,
sourcemap: 'none',
update: true
},
files: {
"<%= src.distFolder %>": "<%= src.sassMain %>"
}
};
//development env.
sass.dev = {
options: {
style: "expanded",
lineNumber: true,
},
files: {
"<%= src.devFolder %>": "<%= src.sassMain %>"
}
};
watch your changes in that case I am watching just sass directory:
//Watch ===============================
config.watch = {
scripts: {
files: ["<%= src.libFolder %>", "<%= src.sassFolder %>"],
tasks: ["dev", "sass:dist"]
//,tasks: ["dev",'sass:dist']
}
}
anyway I hope that helps you for start.
I have the following issue in my gulp build. In one task, I create sprite files for each of my folder and then I run a task compiling sass files which uses spritesmith sass files.
I got the following error :
Error: File to import not found or unreadable: sprites/x
NB: x is the name of my folder in ASSETS_SPRITE_SRC
Here is my spritesmith task
export = function buildAssets(gulp, plugins, option) {
return function () {
var folders = getFolders(ASSETS_SPRITE_SRC);
folders.map(function(folder) {
var spriteData = gulp.src(path.join(ASSETS_SPRITE_SRC, folder, '/*.*'))
.pipe(plugins.spritesmith({
imgName: folder + '.png',
cssName: folder + '.scss'
}));
spriteData.img.pipe(gulp.dest(ASSETS_SPRITE_DEST));
spriteData.css.pipe(gulp.dest(STYLE_SRC + '/sprites'));
});
return gulp.dest(STYLE_SRC + '/sprites');
};
}
function getFolders(dir) {
return fs.readdirSync(dir)
.filter(function(file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
inspired from: https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-task-steps-per-folder.md
And here is my sass task
export = function buildSassDev(gulp, plugins, option) {
return function () {
return gulp.src(join(STYLE_SRC, '**', '*.scss'))
.pipe(plugins.sass().on('error', plugins.sass.logError))
.pipe(gulp.dest(CSS_DEST));
}; }
I run buildAssets first, then buildSassDev.
What I'm wrong about ?
I finally found what I was wrong about. I needed to merge both spriteData.img.pipe and spriteData.css.pipe to be sure they were both ok.
Here is the right code:
export = function buildAssets(gulp, plugins, option) {
return function () {
var folders = getFolders(ASSETS_SPRITE_SRC);
var tasks = folders.map(function (folder) {
var spriteData = gulp.src(path.join(ASSETS_SPRITE_SRC, folder, '/*.*'))
.pipe(plugins.spritesmith({
imgName: folder + '.png',
cssName: folder + '.scss'
}));
var imgStream = spriteData.img.pipe(gulp.dest(ASSETS_SPRITE_DEST));
var cssStream = spriteData.css.pipe(gulp.dest(STYLE_SRC + '/sprites'));
return merge(imgStream, cssStream);
});
return merge(tasks);
};
}