Automated construction

Posted by FireElement on Sat, 04 Dec 2021 06:38:35 +0100

Automated construction

In the development phase, source code is automatically built into production code using efficient syntax, specifications and standards

NPM Script

Whenever npm run is executed, a new Shell will be automatically created and the specified script commands will be executed in this Shell. Therefore, any command that can be run by Shell (usually Bash) can be written in npm script. This means that the node of the current directory_ All scripts in the modules /. Bin subdirectory can be called directly with the script name without adding a path.

"build": "sass sass/main.sass css/style.css --watch",

Don't write it

"build": "./node_modules/.bin/sass sass/main.sass css/style.css --watch",

Default value

Generally speaking, npm scripts are provided by users. However, npm provides default values for both scripts. In other words, these two scripts can be used directly without definition.

"start": "node server.js",
"install": "node-gyp rebuild"

In the above code, the default value of npm run start is node server.js, provided that the script server.js exists in the root directory of the project; The default value of npm run install is node gyp rebuild, provided that there is a binding.gyp file in the root directory of the project.

hook

npm scripts have pre and post hooks. For example, the hooks of the build script command are prebuild and postbuild.

"prebuild": "echo I run before the build script",
"build": "cross-env NODE_ENV=production webpack",
"postbuild": "echo I run after the build script"

When the user executes npm run build, it will be automatically executed in the following order.

npm run prebuild && npm run build && npm run postbuild

npm package

  • NPM run all: start and run multiple commands at the same time

    • Parallel: run multiple commands in parallel, for example: NPM run all -- parallel lint build
    • serial: multiple commands are executed in order, for example: NPM run all -- serial clean lint build:**
    • Continue on error: whether to ignore the error. Adding this parameter NPM run all will automatically exit the command with error and continue to run normally
    • race: after adding this parameter, NPM run all will end all commands as long as one command runs incorrectly
  • browser-sync

Grunt

Basic use

Installation dependency

yarn add grunt

Create the entry file gruntfile.js

// The grunt entry file is used to define tasks that need to be executed automatically by grunt
// A function needs to be exported. This function receives a parameter of grunt and internally provides some APIs that can be used when creating tasks
module.exports = (grunt) => {
  // Register a task named foo
  grunt.registerTask("foo", () => {
    console.log("hello grunt");
  });
  // Register a task named bar and described as task description
  grunt.registerTask("bar", "Task description", () => {
    console.log("other task");
  });
  // To register a default task, you do not need to specify the task name yarn grunt during execution
  // grunt.registerTask("default", () => {
  //   console.log("default task");
  // });
  // Register a default task and execute foo and bar tasks in turn
  grunt.registerTask("default", ["foo", "bar"]);
  // Register an async task asynchronous task
  grunt.registerTask("async-task", function () {
    // Declare that this is an asynchronous task
    this.async();
    setTimeout(() => {
      console.log("async task");
    }, 1000);
  });
};

Execute by command

yarn grunt ${taskName}

Mark task failed

After a task is marked as failed in grunt, subsequent tasks will not be executed. Subsequent tasks of failed tasks can be enforced through the -- force parameter

yarn grunt --force
  • Synchronization task: failed by returning false flag
module.exports = (grunt) => {
  grunt.registerTask("foo", () => {
    console.log("hello grunt");
    return false;
  });
};
  • Asynchronous tasks: through execution status
module.exports = (grunt) => {
  grunt.registerTask("async-task", function () {
    // Declare that this is an asynchronous task
    const done = this.async();
    setTimeout(() => {
      console.log("async task");
      done(false);
    }, 1000);
  });
};

Configuration options method

You can configure the grunt attribute through the grunt.initConfig method

module.exports = (grunt) => {
  grunt.initConfig({
    foo: { name: "jasper" },
  });

  grunt.registerTask("foo", () => {
    console.log(grunt.config().foo.name);
  });
};

Multi objective task

In the initConfig configuration, each attribute under the configuration with the same name as the task is a target. All targets under the configuration can be executed by running the task.

module.exports = (grunt) => {
  grunt.initConfig({
    foo: {
      options: {
        sex: "male",
      },
      name: "jasper",
      age: 25,
    },
  });
  // multiple target
  grunt.registerMultiTask("foo", function () {
    console.log(this.options());
    console.log(`target: ${this.target}, data: ${this.data}`);
  });
};

Plug in use

Install plug-ins

yarn add grunt-contrib-clean --dev

Loading plug-ins

grunt.loadNpmTasks("grunt-contrib-clean");

Configure target

grunt.initConfig({
  clean: {
    temp: "temp/**",
  },
});

implement

yarn grunt clean
module.exports = (grunt) => {
  grunt.loadNpmTasks("grunt-contrib-clean");
  grunt.initConfig({
    clean: {
      temp: "temp/**",
    },
  });
};

Common plug-ins

  • load-grunt-tasks
  • grunt-sass
  • grunt-babel
  • grunt-contrib-watch

Gulp

Basic use

Install gulp

yarn add gulp --dev

Create gulpfile.js file

In the latest gulp, it is agreed that each task is asynchronous, so we need to mark the completion of the task through the done parameter

exports.foo = (done) => {
  console.log("foo task working...");
  done();
};
// Default task
exports.default = (done) => {
  console.log("this is default task");
  done();
};
// gulp 4.0 used to register a task, which is not recommended
const gulp = require("gulp");
gulp.task("old", (done) => {
  console.log("old gulp task..");
  done();
});

Perform tasks

yarn gulp foo

Combined task

We can choose whether the task is paralle l or series according to the specific scenario.

  • The deployment needs to execute the compilation task first. When the deployment task is executed, it should be executed serially
  • During compilation, the compilation of less/sass and js does not have a sequential dependency, so they can be executed in parallel to improve efficiency
const { series, parallel } = require("gulp");

const task1 = (done) => {
  setTimeout(() => {
    console.log("task1 working~");
    done();
  }, 1000);
};

const task2 = (done) => {
  setTimeout(() => {
    console.log("task2 working~");
    done();
  }, 1000);
};
const task3 = (done) => {
  setTimeout(() => {
    console.log("task3 working~");
    done();
  }, 1000);
};

exports.foo = series(task1, task2, task3); //Serial sequential execution

exports.bar = parallel(task1, task2, task3); //Parallel execution

Asynchronous task

Callback function

exports.callback = (done) => {
  console.log("callback task~");
  done();
};

//If multiple tasks are executed, they will not be executed later
exports.callback_error = (done) => {
  console.log("callback_error task~");
  done(new Error("task Failed"));
};

promise

exports.promise = () => {
  console.log("promise task~");
  return Promise.resolve("ok"); //To return a promise object
};

exports.promise_error = () => {
  console.log("promise_error task~");
  return Promise.reject(new Error("task Failed")); //To return a promise object
};

async/await

const timeout = (time) => {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
};
exports.async = async () => {
  await timeout(1000);
  console.log("async task~");
};

Core working principle of Gulp construction process

  • Flow based construction system
const fs = require("fs");
const { Transform } = require("stream");

exports.default = () => {
  //File read stream
  const read = fs.createReadStream("normalize.css");

  //File write stream
  const write = fs.createWriteStream("normalize.min.css");

  //File conversion stream
  const transform = new Transform({
    //
    transform: (chunk, encoding, callback) => {
      //Core conversion process
      //Implementation of core conversion process
      //Chunk = > read content in the read stream (Buffer) toString conversion process string
      const input = chunk.toString();
      const output = input.replace(/\s+/g, "").replace(/\/\*.+?\*\//g, "");
      callback(null, output); //Error first, no error is passed to null
    },
  });

  //Import the read file stream into the write file stream
  read.pipe(transform).pipe(write);

  return read;
};

Gulp file manipulation API

Conversion streams are generally provided through plug-ins. SRC (). Pipe (conversion stream). Pipe (DeST (target directory))

const { src, dest } = require("gulp");
const cleanCss = require("gulp-clean-css");
const rename = require("gulp-rename");

exports.default = () => {
  return src("src/*.css") //Create file read stream
    .pipe(cleanCss())
    .pipe(rename({ extname: ".min.css" })) //Rename extension
    .pipe(dest("dist")); //Export to dest write stream and write parameters to target directory
};

FIS

Basic use

install

yarn add fis3 --dev

Add FIS configuration file fis-conf.js

//Resource location
fis.match("*.{js,scss,png}", {
  release: "/assets/$0", //Current file original directory structure
});
//Compile compression
//yarn global add fis-parser-node-sass
fis.match("**/*.scss", {
  rExt: ".css",
  parser: fis.plugin("node-sass"),
  optimizer: fis.plugin("clean-css"),
});

//yarn global add fis-parser-babel-6.x
fis.match("**/*.js", {
  parser: fis.plugin("babel-6.x"),
  optimizer: fis.plugin("uglify-js"),
});

Execute fis3 inspect to view the conversion file

fis3 release -d output

Topics: Javascript Front-end