8
0
فهرست منبع

Added bundlign task.

Oskar Wrobel 9 سال پیش
والد
کامیت
d8b65407cd

+ 1 - 0
.gitignore

@@ -9,5 +9,6 @@
 
 node_modules/**
 build/**
+bundle/**
 coverage/**
 dist/**

+ 1 - 1
dev/tasks/build/iconmanagermodel.tpl

@@ -5,7 +5,7 @@
 
 'use strict';
 
-import Model from '/ckeditor5/ui/model.js';
+import Model from '../ckeditor5/ui/model.js';
 
 const iconIds = [ {{#shapes}}'{{name}}',{{/shapes}} ];
 const iconPrefix = 'ck-icon-';

+ 15 - 4
dev/tasks/build/tasks.js

@@ -26,9 +26,14 @@ module.exports = ( config ) => {
 		clean: {
 			/**
 			 * Removes "themes" folder from "./build/{format}" directory.
+			 *
+			 * @param {Object} options
+			 * @param {String} options.formats
 			 */
-			themes() {
-				return utils.clean( buildDir, path.join( `@(${ utils.parseArguments().formats.join( '|' ) })`, 'theme' ) );
+			themes( options = {} ) {
+				let formats = options.formats || utils.parseArguments().formats;
+
+				return utils.clean( buildDir, path.join( `@(${ formats.join( '|' ) })`, 'theme' ) );
 			},
 
 			/**
@@ -68,7 +73,7 @@ module.exports = ( config ) => {
 				 * @returns {Stream}
 				 */
 				main( watch ) {
-					const glob = path.join( config.ROOT_DIR, 'ckeditor.js' );
+					const glob = path.join( config.ROOT_DIR, config.MAIN_FILE );
 
 					return gulp.src( glob )
 						.pipe( watch ? gulpWatch( glob ) : utils.noop() );
@@ -332,9 +337,15 @@ module.exports = ( config ) => {
 	gulp.task( 'build:icons', () => tasks.build.icons( args ) );
 	gulp.task( 'build:js', [ 'build:clean:js' ], () => tasks.build.js( args ) );
 
-	// Tasks specific for `gulp docs` builder.
+	// Tasks specific for preparing build with unmodified source files. Uses by `gulp docs` or `gulp bundle`.
 	gulp.task( 'build:clean:js:esnext', () => tasks.clean.js( { formats: [ 'esnext' ] } ) );
+	gulp.task( 'build:clean:themes:esnext', () => tasks.clean.themes( { formats: [ 'esnext' ] } ) );
+	gulp.task( 'build:sass:esnext', () => tasks.build.sass( { formats: [ 'esnext' ] } ) );
+	gulp.task( 'build:icons:esnext', () => tasks.build.icons( { formats: [ 'esnext' ] } ) );
 	gulp.task( 'build:js:esnext', [ 'build:clean:js:esnext' ], () => tasks.build.js( { formats: [ 'esnext' ] } ) );
+	gulp.task( 'build:themes:esnext', ( callback ) => {
+		runSequence( 'build:clean:themes:esnext', 'build:icons:esnext', 'build:sass:esnext', callback );
+	} );
 
 	// Tasks specific for testing under node.
 	gulp.task( 'build:clean:js:cjs', () => tasks.clean.js( { formats: [ 'cjs' ] } ) );

+ 2 - 2
dev/tasks/build/utils.js

@@ -135,7 +135,7 @@ require( [ 'tests' ], bender.defer(), function( err ) {
 	 */
 	transpile( format, options ) {
 		return gulpBabel( options )
-			.on( 'error', function( err ) {
+			.on( 'error', ( err ) => {
 				gutil.log( gutil.colors.red( `Error (Babel:${ format })` ) );
 				gutil.log( gutil.colors.red( err.message ) );
 				console.log( '\n' + err.codeFrame + '\n' );
@@ -165,7 +165,7 @@ require( [ 'tests' ], bender.defer(), function( err ) {
 			plugins: utils.getBabelPlugins( format ),
 			// Ensure that all paths ends with '.js' because Require.JS (unlike Common.JS/System.JS)
 			// will not add it to module names which look like paths.
-			resolveModuleSource: format == 'cjs' ? utils.resolveModuleSource : utils.appendModuleExtension
+			resolveModuleSource: format == 'cjs' ? utils.resolveModuleSource : utils.appendModuleExtension,
 		};
 	},
 

+ 32 - 0
dev/tasks/bundle/classiccreatorbundle.js

@@ -0,0 +1,32 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Bundle configuration for {@link ckeditor5.creator-classic.ClassiCcreator}.
+ *
+ * At this moment we don't know a list of every dependency needed in the bundle. It is because
+ * editor features load automatically during initialization process. To work around this problem
+ * we have created a custom entry file where we defined some of imports with features
+ * needed to initialize editor.
+ */
+
+import 'babel-runtime/regenerator'; // For test
+
+import CKEDITOR from '../../../build/esnext/ckeditor.js';
+import ClassicCreator from '../../../build/esnext/ckeditor5/creator-classic/classiccreator.js';
+
+/**
+ * Wrapper for {@link CKEDITOR.create} which passes default setting
+ * for {@link ckeditor5.creator-classic.ClassiCcreator}. This settings could be extended.
+ * API of this function is exactly the same as {@link CKEDITOR.create}.
+ */
+export default function createEditor( element, config ) {
+	return CKEDITOR.create( element, Object.assign( {
+		creator: ClassicCreator,
+		toolbar: [ 'bold', 'italic' ]
+	}, config ) );
+}

+ 128 - 0
dev/tasks/bundle/tasks.js

@@ -0,0 +1,128 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+const path = require( 'path' );
+const gulp = require( 'gulp' );
+const gulpCssnano = require( 'gulp-cssnano' );
+const gulpUglify = require( 'gulp-uglify' );
+const runSequence = require( 'run-sequence' );
+const utils = require( './utils' );
+const rollup = require( 'rollup' ).rollup;
+const rollupBabel = require( 'rollup-plugin-babel' );
+const rollupCommonJS = require( 'rollup-plugin-commonjs' );
+const rollupNodeResolve = require( 'rollup-plugin-node-resolve' );
+
+module.exports = ( config ) => {
+	const sourceBuildDir = path.join( config.ROOT_DIR, config.BUILD_DIR, 'esnext' );
+	const bundleDir = path.join( config.ROOT_DIR, config.BUNDLE_DIR );
+	const entryFilePath = path.join( config.ROOT_DIR, 'dev', 'tasks', 'bundle', 'classiccreatorbundle.js' );
+
+	const tasks = {
+		/**
+		 * Remove all files from bundle directory.
+		 */
+		clean() {
+			return utils.clean( bundleDir, '*.*' );
+		},
+
+		/**
+		 * Combine whole editor files into two files `ckeditor.js` and `ckeditor.css`.
+		 */
+		generate() {
+			/**
+			 * Bundling JS by Rollup.
+			 *
+			 * At this moment we don't know a list of every dependency needed in the bundle. It is because
+			 * editor features load automatically during initialization process. To work around this problem
+			 * we have created a custom entry file where we defined some of imports with features
+			 * needed to initialize editor.
+			 *
+			 * Bundled `ckeditor.js` file exposes a global function `createEditor`.
+			 * For more details see docs from `classiccreatorbundle.js`.
+			 */
+			function bundleJS() {
+				const outputFile = path.join( bundleDir, config.MAIN_FILE );
+
+				return rollup( {
+					entry: entryFilePath,
+					plugins: [
+						rollupCommonJS( {
+							include: 'node_modules/**'
+						} ),
+						rollupNodeResolve( {
+							jsnext: true
+						} ),
+						rollupBabel( {
+							presets: [ 'es2015-rollup' ]
+						} )
+					]
+				} ).then( ( bundle ) => {
+					return bundle.write( {
+						dest: outputFile,
+						format: 'iife',
+						moduleName: 'createEditor'
+					} );
+				} );
+			}
+
+			/**
+			 * CSS is already bundled by a build task, so we need only to copy it.
+			 */
+			function bundleCSS() {
+				return new Promise( ( resolve ) => {
+					const cssSource = path.join( sourceBuildDir, 'theme', 'ckeditor.css' );
+					utils.copyFile( cssSource, bundleDir, resolve );
+				} );
+			}
+
+			// Lets wait for both - JS and CSS.
+			return Promise.all( [ bundleJS(), bundleCSS() ] );
+		},
+
+		minify: {
+			/**
+			 * JS minification by UglifyJS.
+			 */
+			js() {
+				let stream = gulp.src( path.join( bundleDir, config.MAIN_FILE ) )
+					.pipe( gulpUglify() );
+
+				utils.saveStreamAsMinifiedFile( stream, bundleDir );
+			},
+
+			/**
+			 * CSS minification by cssnano.
+			 */
+			css() {
+				let stream = gulp.src( path.join( bundleDir, 'ckeditor.css' ) )
+					.pipe( gulpCssnano() );
+
+				return utils.saveStreamAsMinifiedFile( stream, bundleDir );
+			}
+		}
+	};
+
+	gulp.task( 'bundle:clean', tasks.clean );
+	gulp.task( 'bundle:generate', [ 'bundle:clean', 'build:js:esnext', 'build:themes:esnext' ], tasks.generate );
+	gulp.task( 'bundle:minify:js', tasks.minify.js );
+	gulp.task( 'bundle:minify:css', tasks.minify.css );
+
+	gulp.task( 'bundle', ( callback ) => {
+		runSequence( 'bundle:generate', [ 'bundle:minify:js', 'bundle:minify:css' ], () => {
+			// Print files size on console just before the end of the task.
+			const files = [ 'ckeditor.js', 'ckeditor.min.js', 'ckeditor.css', 'ckeditor.min.css' ];
+			utils.logFilesSize( files, bundleDir );
+
+			// Finish the task.
+			callback();
+		} );
+	} );
+
+	gulp.task( 'bundle:babelRuntime', tasks.customBabelRuntime );
+
+	return tasks;
+};

+ 80 - 0
dev/tasks/bundle/utils.js

@@ -0,0 +1,80 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+const fs = require( 'fs' );
+const path = require( 'path' );
+const gulp = require( 'gulp' );
+const gulpRename = require( 'gulp-rename' );
+const gutil = require( 'gulp-util' );
+const filesize = require( 'filesize' );
+const clean = require( '../build/utils' ).clean;
+
+const utils = {
+	/**
+	 * Copy file.
+	 *
+	 * @param {String} from source file path
+	 * @param {String} to destination path
+	 * @param {Function} [callback=() => {}] function executed at the end of asynchronous task
+	 * @returns {Stream}
+	 */
+	copyFile( from, to, callback = () => {} ) {
+		return gulp.src( from )
+			.pipe( gulp.dest( to ) )
+			.on( 'end', callback );
+	},
+
+	/**
+	 * Save files from stream in specific destination and add `.min` suffix to the name.
+	 *
+	 * @param {Stream} stream
+	 * @param {String} destination path
+	 * @returns {Stream}
+	 */
+	saveStreamAsMinifiedFile( stream, destination ) {
+		return stream
+			.pipe( gulpRename( {
+				suffix: '.min'
+			} ) )
+			.pipe( gulp.dest( destination ) );
+	},
+
+	/**
+	 * Get human readable size of the file.
+	 *
+	 * @param {String} path path to the file
+	 */
+	getFileSize( path ) {
+		return filesize( fs.statSync( path ).size );
+	},
+
+	/**
+	 * Log on console size of every passed file in specified directory.
+	 *
+	 * 		utils.logFileSize( [ 'ckeditor.min.js', 'ckeditor.min.css' ], 'path/to/dir' );
+	 *
+	 * 		ckeditor.min.js: 192.43 KB
+	 * 		ckeditor.min.css: 5.38 KB
+	 *
+	 * @param {String} [rootDir='']
+	 * @param {Array<String>} files
+	 */
+	logFilesSize( files, rootDir = '' ) {
+		files = files.map( ( file ) => {
+			let filePath = path.join( rootDir, file );
+			let name = path.basename( filePath );
+			let size = utils.getFileSize( filePath );
+
+			return `${name}: ${size}`;
+		} );
+
+		gutil.log( gutil.colors.green( `\n${ files.join( '\n' ) }` ) );
+	}
+};
+
+// Extends utils by a clean method from build utils.
+module.exports = Object.assign( utils, { clean } );

+ 3 - 0
gulpfile.js

@@ -7,7 +7,9 @@ const gulp = require( 'gulp' );
 const config = {
 	ROOT_DIR: '.',
 	BUILD_DIR: 'build',
+	BUNDLE_DIR: 'bundle',
 	WORKSPACE_DIR: '..',
+	MAIN_FILE: 'ckeditor.js',
 
 	// Files ignored by jshint and jscs tasks. Files from .gitignore will be added automatically during tasks execution.
 	IGNORED_FILES: [
@@ -16,6 +18,7 @@ const config = {
 };
 
 require( './dev/tasks/build/tasks' )( config );
+require( './dev/tasks/bundle/tasks' )( config );
 require( './dev/tasks/dev/tasks' )( config );
 require( './dev/tasks/lint/tasks' )( config );
 require( './dev/tasks/test/tasks' )( config );

+ 11 - 0
package.json

@@ -25,8 +25,14 @@
   "devDependencies": {
     "almond": "^0.3.0",
     "babel-core": "^6.4.0",
+    "babel-plugin-transform-es2015-destructuring": "^6.9.0",
+    "babel-plugin-transform-es2015-for-of": "^6.8.0",
     "babel-plugin-transform-es2015-modules-amd": "^6.1.18",
     "babel-plugin-transform-es2015-modules-commonjs": "^6.2.0",
+    "babel-plugin-transform-es2015-parameters": "^6.9.0",
+    "babel-plugin-transform-es2015-shorthand-properties": "^6.8.0",
+    "babel-plugin-transform-es2015-spread": "^6.8.0",
+    "babel-plugin-transform-regenerator": "^6.9.0",
     "benderjs": "^0.4.1",
     "benderjs-chai": "^0.2.0",
     "benderjs-coverage": "^0.2.1",
@@ -36,10 +42,12 @@
     "chai": "^3.4.0",
     "concat-stream": "^1.5.1",
     "del": "^2.0.2",
+    "filesize": "^3.3.0",
     "fs-extra": "^0.26.4",
     "git-guppy": "^1.1.0",
     "gulp": "^3.9.0",
     "gulp-babel": "^6.1.0",
+    "gulp-cssnano": "^2.1.2",
     "gulp-filter": "^3.0.1",
     "gulp-filter-by": "^1.2.0",
     "gulp-istanbul": "^0.10.4",
@@ -53,6 +61,7 @@
     "gulp-replace": "^0.5.4",
     "gulp-sourcemaps": "^1.6.0",
     "gulp-svg-sprite": "^1.2.19",
+    "gulp-uglify": "^1.5.3",
     "gulp-util": "^3.0.7",
     "gulp-watch": "4.3.5",
     "guppy-pre-commit": "^0.3.0",
@@ -69,6 +78,8 @@
     "ncp": "^2.0.0",
     "node-sass": "^3.7.0",
     "replace": "^0.3.0",
+    "rollup": "^0.26.3",
+    "rollup-plugin-babel": "^2.4.0",
     "run-sequence": "^1.1.5",
     "semver": "^5.1.0",
     "shelljs": "^0",