问题
I'm trying to create a prototype at the moment and keep running into walls.
I'm working on a project where we hope to have one code base that all of our end-users use and where the organization that user is affiliated with will determine the skin(css file) that gets applied to the site. Semantic-UI seems like a great fit for this as it has the concept of themes and a build process around it. I wanted to tap into the power of this build process without having to completely rewrite it.
Is there a way to run a semantic ui build task and have it produce multiple css files?
Here is what I've tried so far:
ATTEMPT 1
After running npm install --save-dev semantic-ui
and choosing all of the default options on the install, I updated the semantic/tasks/build.js
file to the following:
/*******************************
Build Task
*******************************/
var
// dependencies
gulp = require('gulp-help')(require('gulp')),
runSequence = require('run-sequence'),
print = require('gulp-print'),
// config
config = require('./config/user'),
install = require('./config/project/install'),
// task sequence
tasks = []
;
// sub-tasks
if(config.rtl) {
require('./collections/rtl')(gulp);
}
require('./collections/build')(gulp);
const orgs = require('../../organizations.json').orgs;
module.exports = function(callback) {
tasks.push('build-javascript');
tasks.push('build-assets');
var lastTaskName = '';
for(var i = 0; i < orgs.length; i ++) {
console.info('Building Semantic');
const org = orgs[i];
gulp.task(`copy semantic ${org}`, function() {
console.info(`copy semantic ${org}`);
return gulp.src(`./orgs/${org}/semantic.json`)
.pipe(print())
.pipe(gulp.dest('../'));
});
gulp.task(`copy theme ${org}`, function() {
console.info(`copy theme ${org}`);
return gulp.src(`./orgs/${org}/theme.config`)
.pipe(print())
.pipe(gulp.dest('./src/'));
});
gulp.task(`build css ${org}`, [`build-css`]);
if( !install.isSetup() ) {
console.error('Cannot find semantic.json. Run "gulp install" to set-up Semantic');
return 1;
}
tasks.push(`copy semantic ${org}`);
tasks.push(`copy theme ${org}`);
tasks.push(`build css ${org}`);
};
runSequence(...tasks, callback);
};
The idea behind this being that for every organization it would have its own semantic.json
and theme.config
files. These would overwrite the default files(/semantic.json
and /semantic/src/theme.config
respectively) and then create a new build-css
task for each one.
The problem with this approach is that the build process only seems to use the original semantic.json
file that was in place before the build started even though it is successfully getting overwritten. For instance, in the original semantic.json
file, the value for output.packaged
is 'dist/'. semantic.json
is successfully getting overwritten and the output.packaged
value is dist/org1
before the build-css
task gets executed, but all of the output files still end up in 'dist/'.
ATTEMPT 2
After running npm install --save-dev semantic-ui
and choosing all of the default options on the install, I updated the semantic/tasks/build/css.js
file to the following:
const console = require('better-console');
const extend = require('extend');
const fs = require('fs');
const gulp = require('gulp');
const autoprefixer = require('gulp-autoprefixer');
const chmod = require('gulp-chmod');
const minifyCSS = require('gulp-clean-css');
const clone = require('gulp-clone');
const concat = require('gulp-concat');
const concatCSS = require('gulp-concat-css');
const dedupe = require('gulp-dedupe');
const flatten = require('gulp-flatten');
const header = require('gulp-header');
const gulpif = require('gulp-if');
const less = require('gulp-less');
const plumber = require('gulp-plumber');
const print = require('gulp-print');
const rename = require('gulp-rename');
const replace = require('gulp-replace');
const uglify = require('gulp-uglify');
const requireDotFile = require('require-dot-file');
const runSequence = require('run-sequence');
const config = require('../config/project/config');
const defaults = require('../config/defaults');
const install = require('../config/project/install');
const tasks = require('../config/tasks');
const banner = tasks.banner;
const comments = tasks.regExp.comments;
const log = tasks.log;
const settings = tasks.settings;
const filenames = tasks.filenames;
const orgs = requireDotFile(`organizations.json`, __dirname).orgs;
module.exports = function(callback) {
orgs.forEach(org => {
const userConfig = requireDotFile(`semantic.${org}.json`, __dirname);
const gulpConfig = (!userConfig) ? extend(true, {}, defaults) : extend(false, {}, defaults, userConfig);
const compiledConfig = config.addDerivedValues(gulpConfig);
const globs = compiledConfig.globs;
const assets = compiledConfig.paths.assets;
const output = compiledConfig.paths.output;
const source = compiledConfig.paths.source;
const cssExt = { extname: `.${org}.css` };
const minCssExt = { extname: `.${org}.min.css` };
let tasksCompleted = 0;
let maybeCallback = function() {
tasksCompleted++;
if(tasksCompleted === 2 * orgs.length) {
callback();
}
};
let stream;
let compressedStream;
let uncompressedStream;
console.info('Building CSS');
if( !install.isSetup() ) {
console.error('Cannot build files. Run "gulp install" to set-up Semantic');
return;
}
// unified css stream
stream = gulp.src(source.definitions + '/**/' + globs.components + '.less')
.pipe(plumber(settings.plumber.less))
.pipe(less(settings.less))
.pipe(autoprefixer(settings.prefix))
.pipe(replace(comments.variables.in, comments.variables.out))
.pipe(replace(comments.license.in, comments.license.out))
.pipe(replace(comments.large.in, comments.large.out))
.pipe(replace(comments.small.in, comments.small.out))
.pipe(replace(comments.tiny.in, comments.tiny.out))
.pipe(flatten())
;
// two concurrent streams from same source to concat release
uncompressedStream = stream.pipe(clone());
compressedStream = stream.pipe(clone());
// uncompressed component css
uncompressedStream
.pipe(plumber())
.pipe(replace(assets.source, assets.uncompressed))
.pipe(rename(cssExt))
.pipe(gulpif(compiledConfig.hasPermission, chmod(compiledConfig.permission)))
.pipe(gulp.dest(output.uncompressed))
.pipe(print(log.created))
.on('end', function() {
runSequence(`package uncompressed css ${org}`, maybeCallback);
})
;
// compressed component css
compressedStream
.pipe(plumber())
.pipe(clone())
.pipe(replace(assets.source, assets.compressed))
.pipe(minifyCSS(settings.minify))
.pipe(rename(minCssExt))
.pipe(gulpif(compiledConfig.hasPermission, chmod(compiledConfig.permission)))
.pipe(gulp.dest(output.compressed))
.pipe(print(log.created))
.on('end', function() {
runSequence(`package compressed css ${org}`, maybeCallback);
})
;
});
gulp.task(`package uncompressed css ${org}`, function() {
return gulp.src(`${output.uncompressed}/**/${globs.components}.${org}${globs.ignored}.css`)
.pipe(plumber())
.pipe(dedupe())
.pipe(replace(assets.uncompressed, assets.packaged))
.pipe(concatCSS(`semantic.${org}.css`, settings.concatCSS))
.pipe(gulpif(compiledConfig.hasPermission, chmod(compiledConfig.permission)))
.pipe(header(banner, settings.header))
.pipe(gulp.dest('dist/'))
.pipe(print(log.created))
;
});
gulp.task(`package compressed css ${org}`, function() {
return gulp.src(`${output.uncompressed}/**/${globs.components}.${org}${globs.ignored}.css`)
.pipe(plumber())
.pipe(dedupe())
.pipe(replace(assets.uncompressed, assets.packaged))
.pipe(concatCSS(`semantic.${org}.min.css`, settings.concatCSS))
.pipe(gulpif(compiledConfig.hasPermission, chmod(compiledConfig.permission)))
.pipe(minifyCSS(settings.concatMinify))
.pipe(header(banner, settings.header))
.pipe(gulp.dest(output.packaged))
.pipe(print(log.created))
;
});
};
The idea behind this being that for every organization it would update a few parameters before running the css build task.
The problem with this approach is that the build process only seems to use the acknowledge a theme.config
file. I tried pointing the build to 'theme.org1.config', etc, but it doesn't work and doesn't provide any error.
ATTEMPT 3 ??? Please let me know if I'm ignoring some obvious route. I've been working on this for a while and no matter how close I think I'm getting, nothing seems to work fully.
Any help would be greatly appreciated!!!
回答1:
I finally got this to work with the following...
I updated ./semantic/build.js
to contain the following:
var
gulp = require('gulp-help')(require('gulp')),
runSequence = require('run-sequence'),
print = require('gulp-print'),
config = require('./config/user'),
install = require('./config/project/install'),
tasks = []
;
if(config.rtl) {
require('./collections/rtl')(gulp);
}
require('./collections/build')(gulp);
const orgs = require('../../build/organizations.json').orgs;
module.exports = function(callback) {
tasks.push('build-javascript');
tasks.push('build-assets');
for(var i = 0; i < orgs.length; i++) {
console.info('Building Semantic');
const org = orgs[i];
gulp.task(`copy theme ${org}`, function() {
return gulp.src(`./src/themes/${org}/theme.config`)
.pipe(gulp.dest('./src/'));
});
gulp.task(`build css ${org}`, [`build-css`]);
gulp.task(`copy output ${org}`, [`build css ${org}`], function() {
return gulp.src(`./dist/**/*.css`)
.pipe(gulp.dest(`../${org}/dist`));
});
if( !install.isSetup() ) {
console.error('Cannot find semantic.json. Run "gulp install" to set-up Semantic');
return 1;
}
tasks.push(`copy theme ${org}`);
tasks.push(`copy output ${org}`);
};
runSequence(...tasks, callback);
};
It takes the idea that I had in ATTEMPT 1 above and just reverses the order of operations a bit. While the build doesn't seem to acknowledge the updated semantic.json
file, it does utilize the updated theme.config
file, so the above script runs the build for each organization and then after that build is done it copies the built files to another directory, updates the theme.config
file and then performs the same process again.
I have the above saved to ./build/override-semantic-ui-build.js
and then I added the following to my package.json
file: "postinstall": "ncp build/override-semantic-ui-build.js semantic/tasks/build.js"
so that when semantic-ui gets installed on the ci server, that build file will get overwritten with the above adaptation.
来源:https://stackoverflow.com/questions/44031816/is-there-a-way-to-build-multiple-semantic-ui-themes-in-the-same-project