Are you still manually compressing images, JS and CSS? Are you still compiling sass, less, coffee manually? Are you still manually merging sprites? Is it still…

Keep it simple. Keep it simple.

In the rapid development of front-end technology today, if you are still in the day after day to repeat the endless physical labor, then you have to reflect, this year do not know how to make a workflow out are embarrassed to say their preschool end.

Javascript is the best programming language, after all. 🙂

Joking aside, what exactly is workflow?

Workflow refers to the automation of part or whole of a business process in a computer application environment. — Baidu Encyclopedia

As mentioned above, the purpose of this sharing topic, “Automated Build”, is to introduce how to build a workflow based on your needs, from the simple to the deep.

A, the premise

Before you read on, bring yourself the following information:

  • Some basic uses of nodejs, such as node index.js;
  • Basic uses of NPM init, (UN)install, run, etc.
  • Learn about gulp and webpack (not used in this chapter)

Please be sure to master the above knowledge points, or you can’t continue to talk, do not aim high; If you’re ready, here we go!

Let’s start with a simple requirement:

  • A local development environment with the ability to monitor file changes and update them in real time;
  • Modify the code, save after the browser automatically refresh
  • Real-time compilation of various precompiled format files
  • Compress and merge static resources and package output
  • The deployment of upload

A word of disagreement is the picture above:




Automated builds (getting started).png


Ok, so with this plan in place, we set out to implement it.

Second, the source

Start by creating a new project folder, project. Next, we open the command line tool, switch to this directory, and start initializing the project:

cd project
npm initCopy the code

Follow the instructions to complete the initialization and open the project to get a package.json file that looks like this:

// package.json {"name": "project", "version": "1.0.0", "description": "a test project", "main": "index.js", "scripts": { "test": "node ./build/test.js" }, "author": "jack lo", "license": "ISC" }Copy the code

Then we first create a source code, the structure is as follows:

- project | - SRC / / source folder | | - TPL | | ` - index. HTML | | - CSS | | ` - index. CSS | | - js | | ` - index. Js | - dist/pack/folder `- package.jsonCopy the code

Compile and package

With everything in place, we started installing the kit, this time using gulp instead of WebPack, and browser-Sync to enable the browser to refresh automatically.

npm install gulp browser-sync --save-devCopy the code

It will take some time.

———- waste time in ———

As a matter of fact, there is a small hole that we need to prepare in advance, because we will use gulp CLI, so we need to install gulp globally.

This is a good habit, and be sure to do it in the future. Record all NPM packages used during development in package.json files for easy use by yourself and others.

npm install gulp -gCopy the code

MAC users may also want to sudo:

sudo npm install gulp -gCopy the code

Press Enter to enter the password as prompted, continue to enter, you can normally install.

———- waste time again in ———

Ok, with the installation done, we can start doing something meaningful.

Gulp is fairly simple to use, with only a few apis. Simply put, write a configuration file called gulpfile.js and execute it from the command line.

First create a new gulpfile.js file in the root directory, then create a random task called test:

// gulpfile.js var gulp = require('gulp') Gulp.task ('test', function () {return console.log('this is a test')})Copy the code

Ok, save. Then we go back to the command line, type the following command and press Enter

gulp testCopy the code

Gulp is followed by the name of the task you want to execute, so we get this result

[22:56:35] Using gulpfile ~/project/gulpfile.js
[22:56:35] Starting 'test'...
this is a test
[22:56:35] Finished 'test' after 149 μsCopy the code

Output text successfully! Congratulations, you have mastered more than half of gulp usage.

Now let’s try to manipulate the file. Let’s copy the HTML file from SRC/HTML into the dist folder (or create a new one if it doesn’t exist).

Gulp.task ('copy', function () {return gulp.src(' SRC/TPL /*.html').pipe(gulp.dest('dist'))})Copy the code

A pipe is a pipe, and you can pipe into pipe, so the workflow can be executed layer by layer, as many tasks as you want to define. This is what gulp is all about, simple workflow. Many people do not understand what GULp does, but here you can get a general idea:

Gulp is a process management tool that defines and executes tasks in a way that is easy to use.

Before gulp, you might have to compile a SASS file, compile it to CSS, then compress it again, then manually copy it to a package folder. One thing that should be done in three steps is a task sei in Gulp:

Gulp.task ('sass', function () { return gulp.src('src/sass/*.scss') .pipe(sass()) .pipe(minifycss()) .pipe(gulp.dest('dist/static')) })Copy the code

We can even execute multiple tasks at the same time. I can define the four tasks of coffee, Sass, image and HTML and combine them into one task to execute them all at once:

Gulp. Task ('build', ['coffee', 'sass', 'image', 'HTML '])Copy the code

I just need to:

gulp buildCopy the code

Hit the car. This is sour.

Well, with all that said, let’s finally get back to the implementation of the original requirements.

Dist /static; dist/static; dist/static; dist/static;

gulp.task('css', function () {
  return gulp.src('src/css/*.css')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('js', function () {
  return gulp.src('src/js/*.js')
  .pipe(gulp.dest('dist/static'))
})

gulp.task('html', function () {
  return gulp.src('src/tpl/*.html')
  .pipe(gulp.dest('dist'))
})

gulp.task('build', ['css', 'js', 'html'])Copy the code

Command line gulp build, enter! Take a look at the dist folder, done!

At first glance, there seems to be nothing wrong, but there seems to be something wrong. No, there is no function other than copying to the dist folder. What about the deal with precompilation? Well, with this framework, we can add as many of these features as we want.

We can’t do anything fancy with this simple project. Let’s use a precompiled language, CSS with Sass and HTML with swig:

- project | - SRC / / source folder | | - TPL | | ` - index. Swig | | - sass | | ` - index. SCSS | | - js | | ` - index. Js | - dist/pack/folder  `- package.jsonCopy the code

Gulp-sass is required to compile SASS, and gulp-swig is required to compile swig. Notice that? Most gulp modules come in the form of gulp-*, so if you want to use a gulp module in the future, try searching for the gulp- module name in NPM.

npm install gulp-sass gulp-swig --save-devCopy the code

———- waste time in ———

Once installed, let’s modify the configuration file gulpfile.js

var gulp = require('gulp') var sass = require('gulp-sass') var swig = require('gulp-swig') gulp.task('sass', function () { return gulp.src('src/sass/*.scss') .pipe(sass({ outputStyle: }).pipe(gulp.dest('dist/static')}) gulp.task('js', function () { return gulp.src('src/js/*.js') .pipe(gulp.dest('dist/static')) }) gulp.task('tpl', function () { return gulp.src('src/tpl/*.swig') .pipe(swig({ defaults: { cache: False / / this configuration is forced to compile the file does not cache}})) pipe (gulp. Dest (' dist ')}) gulp. Task (' build '[' sass', 'js',' the TPL '])Copy the code

Dist /static/index.css (dist/static/index.html) The source and packaged files are not shown here, because they are not important. If you want to see the demo project content, you can find the link to the Git repository for this demo project at the end of this article. All kinds of preprogramming languages and front-end templates can be selected according to their preferences, the author just choose their own familiar several to do the demo.

Now that we’re pretty much done with the packaging, let’s try to set up the development environment.

4. Build the development environment

Remember browser-sync, the tool we mentioned earlier? Now it comes in handy! We started by creating a development task, something as simple as Gulp Build. Our goal was to do it without cavities.

gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () {
  // do something here...
})Copy the code

It looks a little different. This time we create a task called dev, which executes js:dev, sass:dev, and TPL :dev before executing the callback where our local server is defined and started.

Before we do that, let’s take a look at Browser-sync:

Browsersync lets the browser respond to changes to your files (HTML, JS, CSS, Sass, LESS, etc.) in real time and refresh the page automatically. – Browsersync Chinese website

In fact, Browsersync can be understood as a local server, similar to Apache, but Browsersync only provides very simple HTTP functions. Its main function is to set up a local server, listen for file changes, automatically refresh the browser, and present the latest content in real time.

Browser-sync

Var browserSync = require('browser-sync').create() browsersync.init ({server: {baseDir: ".Copy the code

It’s pretty simple, it doesn’t have a lot of content. Now we’re going to integrate it into our gulp task.

gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () { browserSync.init({ server: { baseDir: "./dist" // Set the server root directory to dist}, notify: False // Enable silent mode}) Gulp.watch (' SRC /js/*.js', ['js:dev']) gulp.watch(' SRC /sass/*.scss', ['sass:dev']) gulp.watch('src/tpl/*.swig', ['tpl:dev']) })Copy the code

The behavior of watch here can be simply interpreted as: I (gulp) keep an eye on you (SRC /js/*.js), and as soon as you change, I execute js:dev to process you and produce the latest file.

Js :dev, sass:dev, TPL :dev, sass:dev, sass:dev, TPL :dev, sass:dev

var browserSync = require('browser-sync').create() var reload = browserSync.reload gulp.task('sass:dev', function () { return gulp.src('src/sass/*.scss') .pipe(sass()) .pipe(gulp.dest('dist/static')) .pipe(reload({stream: true})) }) gulp.task('js:dev', function () { return gulp.src('src/js/*.js') .pipe(gulp.dest('dist/static')) .pipe(reload({stream: true})) }) gulp.task('tpl:dev', function () { return gulp.src('src/tpl/*.swig') .pipe(swig({ defaults: { cache: Pipe (gulp.dest('dist')).pipe(reload({stream: true}))})Copy the code

We don’t need to know much about the Reload method here, just that it is executed to refresh the browser. The use of stream here can be found in the official documentation, so it is not important to go into detail here.

Sass :dev: sass:dev: sass:dev: sass:dev: sass:dev: sass:dev: sass:dev: sass In fact, we in the development, does not need to compress the static resource file, it’s safe to say we don’t care about it is bigger or smaller size, we care about is whether the style to write is in line with expectations, we care about is whether the function implementation, so there’s no need to enable compression or what other optimization function, so that we can reduce the burden of compilation, speed up the compilation. If you use compression for JS or images, it is recommended that you leave it in development mode and only use it in package mode.

Gulpfile.js:

var gulp = require('gulp') var sass = require('gulp-sass') var swig = require('gulp-swig') var browserSync = require('browser-sync').create() var reload = browserSync.reload gulp.task('sass', function () { return gulp.src('src/sass/*.scss') .pipe(sass({ outputStyle: }).pipe(gulp.dest('dist/static')}) gulp.task('js', function () { return gulp.src('src/js/*.js') .pipe(gulp.dest('dist/static')) }) gulp.task('tpl', function () { return gulp.src('src/tpl/*.swig') .pipe(swig({ defaults: { cache: False // This configuration forces compiled files not to be cached}})).pipe(gulp.dest('dist'))}) gulp.task('sass:dev', function () { return gulp.src('src/sass/*.scss') .pipe(sass()) .pipe(gulp.dest('dist/static')) .pipe(reload({stream: true})) }) gulp.task('js:dev', function () { return gulp.src('src/js/*.js') .pipe(gulp.dest('dist/static')) .pipe(reload({stream: true})) }) gulp.task('tpl:dev', function () { return gulp.src('src/tpl/*.swig') .pipe(swig({ defaults: { cache: Pipe (gulp.dest('dist')).pipe(reload({stream: true})) }) gulp.task('dev', ['js:dev', 'sass:dev', 'tpl:dev'], function () { browserSync.init({ server: { baseDir: "./dist" }, notify: false }) gulp.watch('src/js/*.js', ['js:dev']) gulp.watch('src/sass/*.scss', ['sass:dev']) gulp.watch('src/tpl/*.swig', ['tpl:dev']) }) gulp.task('build', ['sass', 'js', 'tpl'])Copy the code

Well, perfect. At this point, our automated build is pretty much complete, and still pretty much complete. Is it convenient for us to execute gulp dev when we develop and gulp build when we package?

Note: The gulp dev task is kept alive after it is started, which means it is not executed all at once like gulp build. Therefore, to stop the task, we need to manually press CTRL + C to end the task.

Five, the complement

However, things are not over, our goal is: pretend to be perfect!

There are three things we haven’t done yet:

  • Wrap commands as succinctly as possible. Gulp dev and gulp Build are pretty neat, but in fact they are simple and require very few commands. When developing a complex project, you usually have to enter a long and complex command line. Gulp dev is the default for gulp –gulpfile gulpfile.js dev. So we need a cleaner way to execute these pre-prepared scripts, like shortcuts on Windows;
  • The current situation is that every time we execute, we copy files to dist directory, but there is no deletion work, that is to say, the number of files only increases, so many useless files will be left over with the addition and deletion of files. We need to delete the entire dist folder before starting compilation or packaging, and then regenerate dist;
  • The upload function hasn’t been done yet? !

Get to work without another word!

The first is easy to fix, and we can store the script as a configuration in package.json:

{" name ":" the project ", "version" : "1.0.0", "description" : "a test project", "main" : "index. Js", "scripts" : {" dev ": "Gulp dev", // develop script "build": "gulp build", // package script "test": "node./build/test.js"}, "author":" Jack lo", "license": "ISC", "devDependencies" : {" browser - sync ":" ^ 2.13.0 ", "gulp" : "^ 3.9.1", "gulp - sass" : "^" 2.3.2, "gulp - swig" : "^ 0.8.0}}"Copy the code

Notice that? The scripts TAB is used to pre-define the script. We can easily encapsulate the script in the form above, and then execute it as follows:

NPM run dev NPM run buildCopy the code

Done!

Let’s move on to the second point, delete the dist folder. How easy! Right mouse button, delete, done!

Which have so low things, our goal is: lazy cancer can not do their own things, never start their own hands.

There is a package called Rimraf that does this for us, and we need to use its CLI, so like gulp, we install it globally:

npm install rimraf -gCopy the code

After the installation, we will modify the contents of the scripts in package.json file again:

{" name ":" the project ", "version" : "1.0.0", "description" : "a test project", "main" : "index. Js", "scripts" : {" dev ": "Gulp dev", // develop script "build": "rimraf dist && gulp build", // package script "test": "node./build/test.js"}, "author": "Jack lo", "license" : "ISC", "devDependencies" : {" browser - sync ":" ^ 2.13.0 ", "gulp" : "^ 3.9.1", "gulp - sass" : "^2.3.2", "gulp-swig": "^0.8.0"}}Copy the code

NPM run build: Dist was deleted and then regenerated.

Perfect.

Third point in the last to supplement, mainly considering that it is not necessary, because some projects do not need to FTP upload, generally is submitted to SVN, and then by the backend or operational deployment, the author is the need to upload the static resources to CDN server for accelerated, so need such a task, we make a brief introduction here.

Create an upload task:

var ftp = require('gulp-ftp') var gutil = require('gulp-util') gulp.task('upload', Function () {return gulp.src('dist/**'). Pipe (FTP ({host: '8.8.8.8', // remote host IP: 22, // remote host IP: 22, // remote host IP: 22, // remote user: 'username', // account pass: 'password', // password remotePath: '/project' // upload path, new if not present})).pipe(gutil.noop())})Copy the code

Install gulp-ftp and gulp-util packages yourself, then add a script NPM run upload to the scripts in package.json file to perform gulp upload.

I usually upload the file after packing, type NPM run build && NPM run upload, press enter, and then I can happily chat with the girl next to me.

Six, summarized

At this point, we have completed a set of simple automation tools, which seems to cover a lot of things, but in fact it is very little: we just use three small tasks (Sass, JS, TPL) to make up two big tasks, build and dev, and that’s it. Under the condition of skilled operation, the whole process is only ten minutes!

Ps: Is it my fault that the network is so bad? Ha ha.

Due to time and space, we only dealt with CSS, JS, and HTML. In fact, you can build on this. Js can be compiled from CoffeeJS, and can be compressed, or even combined into a single JS file! HTML can be compressed as well. Also, you can create your own task to handle other things like images, fonts, etc.

Well, that’s all for the easy version.

Last word: Gulp and Webpack are both popular compilation and packaging tools, so what are the similarities and differences between them? How to choose? Keep an eye out for the difference in the next section, which explains how to build a development tool with WebPack.

The git address for this demo project is gulp_base

Next: Step Up: Build projects with version management capabilities

(If there are any fallacies in the article, please leave comments.)