Bladeren bron

Changed the way of generating bundle - from static hard coded entry file to configuration file.

Oskar Wrobel 9 jaren geleden
bovenliggende
commit
ac891051ff
3 gewijzigde bestanden met toevoegingen van 127 en 15 verwijderingen
  1. 18 0
      dev/tasks/bundle/bundle-config.js
  2. 42 12
      dev/tasks/bundle/tasks.js
  3. 67 3
      dev/tasks/bundle/utils.js

+ 18 - 0
dev/tasks/bundle/bundle-config.js

@@ -0,0 +1,18 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+module.exports = {
+	creator: './build/esnext/ckeditor5/editor-classic/classic.js',
+	moduleName: 'MyCKEditor',
+	features: [
+		'./build/esnext/ckeditor5/enter/enter.js',
+		'./build/esnext/ckeditor5/paragraph/paragraph.js',
+		'./build/esnext/ckeditor5/typing/typing.js',
+		'./build/esnext/ckeditor5/undo/undo.js',
+		'./build/esnext/ckeditor5/headings/headings.js'
+	]
+};

+ 42 - 12
dev/tasks/bundle/tasks.js

@@ -5,19 +5,22 @@
 
 'use strict';
 
+const fs = require( 'fs' );
 const path = require( 'path' );
 const gulp = require( 'gulp' );
 const gulpCssnano = require( 'gulp-cssnano' );
 const gulpUglify = require( 'gulp-uglify' );
+const gutil = require( 'gulp-util' );
 const runSequence = require( 'run-sequence' );
 const utils = require( './utils' );
 const rollup = require( 'rollup' ).rollup;
 const rollupBabel = require( 'rollup-plugin-babel' );
 
 module.exports = ( config ) => {
+	const args = utils.parseArguments();
 	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', 'buildclassiceditor.js' );
+	const temporaryEntryFilePath = './tmp/entryfile.js';
 
 	const tasks = {
 		/**
@@ -29,23 +32,33 @@ module.exports = ( config ) => {
 
 		/**
 		 * Combine whole editor files into two files `ckeditor.js` and `ckeditor.css`.
+		 *
+		 * @param {String} configFilePath Path to the bundle configuration file.
+		 * @return {Promise} Promise that resolve bundling for CSS anf JS.
 		 */
-		generate() {
+		generate( configFilePath ) {
+			// When config file is not specified.
+			if ( !configFilePath ) {
+				// Then log error.
+				gutil.log( gutil.colors.red( `Bundle Error: Path to the config file is required. 'gulp bundle --config path/to/file.js'` ) );
+				// And stop process as failed.
+				process.exit( 1 );
+			}
+
+			// Get configuration from the configuration file.
+			const config = require( path.resolve( '.', configFilePath ) );
+
+			// Create temporary entry file.
+			fs.writeFileSync( temporaryEntryFilePath, utils.renderEntryFileContent( config ) );
+
 			/**
 			 * 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.
-			 *
-			 * For more details see `buildclassiceditor.js`.
 			 */
 			function bundleJS() {
 				const outputFile = path.join( bundleDir, 'ckeditor.js' );
 
 				return rollup( {
-					entry: entryFilePath,
+					entry: temporaryEntryFilePath,
 					plugins: [
 						rollupBabel( {
 							presets: [ 'es2015-rollup' ]
@@ -55,8 +68,18 @@ module.exports = ( config ) => {
 					return bundle.write( {
 						dest: outputFile,
 						format: 'iife',
-						moduleName: 'ClassicEditor'
+						moduleName: config.moduleName
 					} );
+				} ).then( () => {
+					// If everything went well then remove temporary entry file.
+					utils.clean( '', temporaryEntryFilePath );
+				} ).catch( ( err ) => {
+					// If something went wrong then log error.
+					gutil.log( gutil.colors.red( `Bundle Error` ) );
+					gutil.log( gutil.colors.red( err.stack ) );
+
+					// And remove temporary entry file.
+					utils.clean( '', temporaryEntryFilePath );
 				} );
 			}
 
@@ -97,7 +120,14 @@ module.exports = ( config ) => {
 
 		register() {
 			gulp.task( 'bundle:clean', tasks.clean );
-			gulp.task( 'bundle:generate', [ 'bundle:clean', 'build:js:esnext', 'build:themes:esnext' ], tasks.generate );
+			gulp.task( 'bundle:generate',
+				[
+					'bundle:clean',
+					'build:js:esnext',
+					'build:themes:esnext'
+				],
+				() => tasks.generate( args.config )
+			);
 			gulp.task( 'bundle:minify:js', tasks.minify.js );
 			gulp.task( 'bundle:minify:css', tasks.minify.css );
 			gulp.task( 'bundle:next', tasks.next );

+ 67 - 3
dev/tasks/bundle/utils.js

@@ -13,9 +13,73 @@ const gutil = require( 'gulp-util' );
 const prettyBytes = require( 'pretty-bytes' );
 const gzipSize = require( 'gzip-size' );
 const mainUtils = require( '../utils' );
+const minimist = require( 'minimist' );
 
 const utils = {
 	/**
+	 * Parses command line arguments and returns them as a user-friendly hash.
+	 *
+	 * @returns {Object} options
+	 * @returns {String} [options.config] Path to the bundle configuration file.
+	 */
+	parseArguments() {
+		const options = minimist( process.argv.slice( 2 ), {
+			string: [
+				'config'
+			]
+		} );
+
+		return options;
+	},
+
+	/**
+	 * Render content for entry file which needs to be passed as main file to Rollup.
+	 *
+	 * @param {Object} data
+	 * @param {String} [data.moduleName] Name of the editor class exposed in bundle. e.g. MyCKEditor.
+	 * @param {String} [data.creator] Path to the editor creator as ClassicEditor, StandardEditor etc.
+	 * @param {Array<String>} [data.features] List of paths or names to features which need to be included in bundle.
+	 * @returns {string}
+	 */
+	renderEntryFileContent( data ) {
+		const creatorName = path.basename( data.creator, '.js' );
+		const creatorPath = path.relative( './tmp', data.creator );
+		let featureNames = [];
+		let template = `'use strict';\n\n`;
+
+		// Imports babel helpers.
+		template += `import '../node_modules/regenerator-runtime/runtime.js';\n`;
+
+		// Imports editor creator
+		template += `import ${ creatorName } from '${ creatorPath }';\n`;
+
+		// Imports editor features.
+		for ( let feature of data.features ) {
+			const featureName = path.basename( feature, '.js' );
+			const featurePath = path.relative( './tmp', feature );
+
+			template += `import ${ featureName } from '${ featurePath }';\n`;
+			featureNames.push( featureName );
+		}
+
+		// Class definition.
+		template += `\nexport default class ${ data.moduleName } extends ${ creatorName } {
+	static create( element, config = {} ) {
+		if ( !config.features ) {
+			config.features = [];
+		}
+
+		config.features = [ ...config.features, ${ featureNames.join( ', ' ) } ];
+
+		return ${ creatorName }.create( element, config );
+	}
+}
+`;
+
+		return template;
+	},
+
+	/**
 	 * Save files from stream in specific destination and add `.min` suffix to the name.
 	 *
 	 * @param {Stream} stream
@@ -87,9 +151,9 @@ const utils = {
 	/**
 	 * Print on console list of files with their size stats.
 	 *
-	 * 		Title:
-	 * 		file.js: 1 MB (gzipped: 400 kB)
-	 * 		file.css 500 kB (gzipped: 100 kB)
+	 *        Title:
+	 *        file.js: 1 MB (gzipped: 400 kB)
+	 *        file.css 500 kB (gzipped: 100 kB)
 	 *
 	 * @param {String} title
 	 * @param {Array<Object>} filesStats