introduce

There are a lot of great build tools in front end history, such as NPM Script, Grunt, gulp, FIS3, Webpack, rollup, Parcel, etc. It is precisely because of the rapid development of front-end technology that there are various tools to improve development efficiency, to increase productivity and reduce development costs. There are two main points to learn from this article

  • A comparison and pros and cons of the major build tools
  • Summary and configuration of common plug-ins for WebPack

Build tool role

Before we look at the various build tools, we need to understand what a build tool does. In effect, it turns source code into executable code. Such as converting javaScript, CSS, HTML, etc. The following functions are included in the transformation process

  • Convert code into code that can be executed in the browser (ES6, SASS, LESS, etc.)
  • Code and page level, resource level optimization (compression, obfuscation, merging, caching, etc.)
  • Conduct code segmentation, module combination, specification verification, etc. (extract common code of page, etc.)
  • Development hot update, separate environment automatic release, etc

All that is said above is actually the idea of engineering and automation. Use tools to automatically solve a series of complex operations using manual processes, freeing productivity.

Build Tool comparison

To better understand the application scenarios and advantages and disadvantages of current build tools, let’s take a look

npm


NPM Scripts Usage Guide

Npm Scripts (Npm Scripts) is a task performer. NPM is a package manager that comes with Node installation. NPM Script is a built-in feature of NPM that allows you to define tasks using the scripts field in package.json files:

{
    "scripts": {"dev": "node dev.js"."pub": "node build.js"}}Copy the code

The scripts field is an object, and each property corresponds to a Shell script. The above code defines two tasks, dev and pub. The underlying implementation principle is to run script commands by calling the Shell. For example, executing the NPM run pub command is equivalent to executing the Node build.js command.

Advantages: NPM Scripts has the advantage of being built-in and does not need to install other dependencies. Disadvantages: It provides pre and POST hooks, but cannot easily manage dependencies between multiple tasks.

grunt


Grunt website

Grunt is now largely out of use. Just to be brief. Grunt, like Npm Scripts, is a task-taker. Grunt has a large number of plugins that encapsulate common tasks, manage dependencies between tasks, and automate the execution of dependencies. The specific execution code and dependencies for each task are written in the configuration file gruntfile.js.

Advantages: Flexible, it is only responsible for performing tasks we have defined. A number of reusable plug-ins encapsulate common build tasks. Disadvantages: integration is not high, to write a lot of configuration can be used, can not do out of the box

gulp


Gulp website

Gulp is a stream-based automated build tool. In addition to managing and executing tasks, it also supports listening to files and reading and writing files. Gulp is designed to be simple enough to support almost any build scenario with just five methods:

  • Register a task with gulp.task
  • Execute the task using gulp.run
  • Listen for file changes through gulp.watch
  • Read the file from gulp.src
  • Finish writing the file through gulp.dest
// General method
/ / into the Gulp
var gulp = require("gulp");
// Import plug-ins
var jshint = require("gulp-jshint");
var sass = require("gulp-sass");
var concat = require("gulp-concat"); ./ / SCSS task
gulp.task('scss'.function() {
    // Read the file and execute the plug-in through the pipe
    gulp.src('./scss/*.scss')
        // The SCSS plug-in compiles SCSS files to CSS
        .pipe(sass())
        // Output file
        .pipe(guilp.dest('./css'));
});
// Merge compressed JavaScript files
gulp.task('scripts'.function() {
    gulp.src('./js/*.js')
        .pipe(concat('all.js'))
        .pipe(uglify())
        .pipe(gulp.dest('./dest'));
});
// Listen for file changes
gulp.task('watch'.function() {
    // The SCSS task is executed when the SCSS file is edited
    gulp.watch('./scss/*.scss'['sass']);
    gulp.watch('./js/*.js'['scripts']);
});
Copy the code

Advantages: Easy to use and flexible, it can be built alone or used with other tools. Disadvantages: Low integration, need to write a lot of configuration before it can be used, cannot be used out of the box

Gulp can be seen as an enhanced version of Grunt. Compared with Grunt, Gulp has the functions of file listening, reading and writing, and streaming processing.

fis3


Fis3 website

Fis3 is an excellent domestic build tool from Baidu. Compared with Grunt and Gulp, these tools only provide basic functions. Fis3 integrates build features commonly used by developers, as described below.

  • Read and write files: use fis. Match to read files and release to configure the output path of files.
  • Resource location: Resolves dependencies between files and file locations.
  • File fingerprint: When using useHash to configure the output file, add md5 stamps to the URL of the file to optimize the browser cache.
  • File compilation: Use the Parser to convert files, such as COMPILING ES6 to ES5.
  • Compressed resources: Configure the code compression method using the Optimizer.
  • Image merge: Use the Spriter configuration to merge images imported from CSS into a single file to reduce HTTP requests.
/ / add the md5
fis.match('*.{js,css,png}', {
    useHash: true
});
// The fis3-parse-typescript plug-in converts typescript files to JavaScript files
fis.match('*.ts', {
    parser: fis.plugin('typescript')});// Merge the CSS Sprite diagram
fis.match('*.css', {
    // Assign the useSprite attribute to the matched file
    useSprite: true
});
/ / compressed JavaScript
fis.match('*.js', {
    optimizer: fis.plugin('uglify-js')});/ / compress CSS
fis.match('*.css', {
    optimizer: fis.plugin('clean-css')});// Compress the image
fis.match('*.png', {
    optimizer: fis.plugin('png-compressor')});Copy the code

Advantages: It integrates various Web building functions and is easy to configure and use out of the box. Disadvantages: It is no longer updated and maintained officially and does not support Node of the latest version

Webpack website

Webpack is a tool to package modular JavaScript. In Webpack, all files are modules, through loader to convert files, through Plugin to inject hooks, and finally output files composed of multiple modules. Webpack focuses on building modular projects.

// General method
module.exports = {
    entry: './app.js'.output: {
        filename: 'bundle.js'}}Copy the code

Advantages:

  • Focus on the processing of modular projects, can do out of the box, one step in place;
  • Plugin can be extended, complete and easy to use without losing flexibility;
  • Usage scenarios are not limited to Web development;
  • The community is large and active, often introducing new features that keep up with The Times, and finding existing open source extensions for most scenarios;
  • Good development experience;

Disadvantages:

Only for projects with modular development

rollup


The rollup’s official website

Rollup is a module packaging tool similar to WebPack but focused on ES6. Its highlight is Tree Shaking ES6 source code to remove code that has been defined but not used and Scope it in order to reduce output file size and improve performance. However, these highlights of Rollup have since been imitated and implemented by WebPack. Since Rollup is used in much the same way as WebPack, I won’t go into the details of how to use Rollup here, but rather explain the differences:

  • Rollup was an alternative to WebPack when it became popular;
  • Rollup ecological chain is not perfect, the experience is not as good as Webpack;
  • Rollup is not as featureas WebPack, but it is simpler to configure and use;
  • Rollup does not support Code Spliting, but the benefit is that there is no webpack loading, executing, and caching Code in the packaged Code.
  • Rollup has an advantage over WebPack when it comes to packaging JavaScript libraries because the code it packages is smaller and faster. However, its functionality is not perfect enough to find a ready-made solution in many scenarios

parcel


The parcel’s official website

Parcel is suitable for developers with varying experience. It takes advantage of multi-core processing to provide extremely fast speed and requires no configuration. Out of the box.

Advantages:

  • Pack fast. Parcel uses the worker process to enable multicore compilation. It also has a file system cache, allowing fast recompilation even after a restart build.
  • Out of the box. Support for JS, CSS, HTML, files and more, and no plug-ins required.
  • Automatic conversion. Babel, PostCSS, and PostHTML and even node_modules packages can be used to automatically convert code if needed.
  • Replace the hot module. Parcel requires no configuration and automatically updates modules in the browser as your code changes while you’re developing your environment.
  • Friendly error log. When you encounter an error, Parcel outputs syntax-highlighted snippets of code to help you locate the problem.

Disadvantages:

  • Does not support SourceMap: In development mode, Parcel does not output SourceMap and can only debug very unreadable code for now;
  • TreeShaking is not supported: Many times we use only one function in the library and a Parcel wraps up the entire library.
  • Some dependencies cause a Parcel to fail: Some Npm modules cause a Parcel to run incorrectly when your project relies on modules on Npm.
  • Inflexible configuration: A zero-configuration Parcel turns off many configuration items and cannot be changed in cases where the configuration is required
  • Scenarios are limited: they can only be used to build web pages that run in a browser

From the above comparison we can see that each build tool actually has its own application scenario. Every tool was born of The Times. So in recent years popular modularization, componentalization also appeared a lot of component libraries, CMD specification seaJs, AMD specification requireJs and so on (difference), this specification is nothing more than to solve the actual problems in development. So why did we choose Webpack?

  • Current front-end technology will adopt new ideas (modular + new language + new framework) to develop
  • Webpack can be configured almost to zero after 4.0
  • Can provide a one-stop solution for new projects
  • Have good ecology and maintenance team, abundant learning resources and can guarantee good experience and quality
  • The popularity of the CLI for the Vue and React libraries was also a factor

So let me take a look at how WebPack works

Webpack principle

Let’s look at the basic build concepts and build processes before we look at the principles

The basic concept


  • Entry Entry file to build
  • Output The location of the file output after the build is completed
  • Module, which processes files by matching rules and loader
  • Loader (ES6 -> ES5, etc.)
  • Plugins that extend functionality by listening to hook functions on the execution process
  • Chunk code composed of multiple files is fast
// Simple example
const webpackConfig = {
  mode: _mode == "test" ? "development" : _mode,
  entry: {
    main: "./src/main.js"
  },
  output: {
    path: join(__dirname, "./dist/assets")},module: {
    // ...
  },
  optimization: {
    // ...
  },
  plugins: [..._plugins, new VueLoaderPlugin()],
  externals: {
    ..._externals
  },
  resolve: {
   // ...}};Copy the code

Run the process


Webpack is like a production line that goes through a series of processes to convert source files into output. Each process on this production line has a single responsibility. There are dependencies between multiple processes. Only after the current process is completed can the next process be handled. A plug-in is like a function that plugs into a production line and works with resources on the production line at a specific time.

Webpack organizes this complex production line through Tapable. Webpack broadcasts events as it runs, and the plug-in only needs to listen for the events it cares about to join the production line and change how the production line works. Webpack’s event flow mechanism ensures the orderliness of plug-ins and makes the whole system very extensible. — Wu Haolin, “Simple Webpack”

The above paragraph explains exactly what Webapck does, which is essentially handle different functions at build time through a series of event handlers and callbacks. This flow of events is managed by Tapable. For Tapable, please refer to the source code analysis of big Guy.

However, webpack4 rewrites the event flow mechanism Webpack Hook due to the complexity of the source code. It will be arranged by mind mapping in the back to facilitate memory. So webpack5 actually added some functionality. I won’t go into the discussion here.

The following is a flow chart to analyze the implementation process of Webpack

  • First read the webpack.config.js file and initialize the configuration parameters for this build
  • The initialization parameter phase begins by reading configuration Entries and iterating through all entry files.
  • Enter each entry file in turn and use the configured Loader to parse and compile the file content and generate AST (static syntax tree).
  • Finally, it outputs chunk of code, packaged files and so on

The above process is only a cursory overview of the execution process, so let’s take a look at how webPack works inside

The diagram above has made it clear what to do at each stage of WebPack. Being familiar with the process helps us understand daily development. Below we list some common Loaders and plugins for daily development

Webpack commonly used plug-ins

We introduce our common functions and plug-ins through the pseudo-code configuration

mode


const webpackConfig  = {
  mode: _mode == "test" ? "development" : 'production',}Copy the code

Mode allows us to control whether we are in the development or online environment by controlling the environment to distinguish between the files being executed. If production is not included in our configuration, Webpack will enable the following plug-ins by default

  • FlagDependencyUsagePlugin tag (compile time dependent)
  • FlagIncludedChunksPlugin
  • ModuleConcatenationPlugin (scope hoisting, precompiled function, promote the speed of execution for the code in the browser)
  • NoEmitOnErrorsPlugin (skip the output phase if errors are encountered at compile time to ensure that the output resource does not contain errors)
  • OccurrenceOrderPlugin (Sort generated chunkid)
  • SideEffectsFlagPlugin (SideEffects for Module. rules)
  • Uglifyjs-webpack-plugin (Remove unreferenced code and compress JS)

entry


Single page entry configuration

const webpackConfig  = {
  mode: _mode == "test" ? "development" : 'production'.entry: {
    main: "./src/main.js"}}Copy the code

Multi-page entry configuration

const webpackConfig  = {
  mode: _mode == "test" ? "development" : 'production'.entry: {
    pageOne: './src/pageOne/index.js'.pageTwo: './src/pageTwo/index.js'.pageThree: './src/pageThree/index.js'}}Copy the code

output


const webpackConfig  = {
  / /...
  output: {
    path: join(__dirname, "./dist/assets")}}Copy the code

You can also set hash and publicPath for the output file. The publicPath can set the CDN address to optimize the file loading time

const webpackConfig  = {
  // ...
  output: {
    filename: "scripts/[name].[contenthash:5].bundule.js".publicPath: "/assets/"}}Copy the code

module


// loaders
const webpackConfig  = {
  // ...
  module: {
    // When creating a module, match the array of rules requested
    // Use these rules to apply the loader to modules and/or modify the parse.
    rules: [
      {
        test: /\.js$/.// Match rules
        exclude: /(node_modules|bower_components)/.// Exclude files
        use: {
          loader: "babel-loader"  // The loader to use}}, {test: /\.vue$/.loader: "vue-loader"
      },
      {
        test: /\.(png|jpg|gif)$/i.use: [{loader: "url-loader".options: {
              // An inline file smaller than 10kB(10240 bytes)
              limit: 5 * 1024.name: _modeflag
                ? "images/[name].[contenthash:5].[ext]"
                : "images/[name].[ext]"}}]}},}Copy the code

For more configuration parameters, please refer to webPack’s official website

plugin


// plugins
const webpackConfig  = {
  // ...
  plugins: [
    // Analyze the current package size
    new BundleAnalyzerPlugin(),
    // Create an HTML entry file
    new HtmlwebpackPlugin({
      filename: "index.html".template: "./src/index-dev.html"
    }),
    // Webpack builds error and warning notifications
    new webpackBuildNotifierPlugin({
      title: "Front-end project".logo: resolve("./favicon.png"),
      suppressSuccess: true
    }),
    // Friendly prompt plugin
    new FriendlyErrorsPlugin({
      compilationSuccessInfo: {
        messages: ["You application is running here http://localhost:8080"].notes: ["Please run this service after configuring the proxy."]},// Suggest good tools for more detailed presentation
      onErrors: function(severity, errors) {},
      clearConsole: true}})]Copy the code

OptimizeCssAssetsPlugin and MiniCssExtractPlugin can be used for CSS optimization in the online environment. The ProgressBarPlugin progress bar is not listed here.

optimization


// Optimize the configuration
const webpackConfig = {
  // ...
  optimization: {
    runtimeChunk: {
      name: "runtime"
    },
    splitChunks: {
      chunks: "async".minSize: 30000.minChunks: 1.maxAsyncRequests: 5.maxInitialRequests: 3.name: false.cacheGroups: {
        commons: {
          chunks: "initial".minChunks: 2.maxInitialRequests: 5.minSize: 0.name: "commons"
        }
      }
    }
  }
}
Copy the code

For more parameters and plugins, see the Webapck website

externals


// External extension
const webpackConfig = {
  // ...
  externals: {
    vue: "Vue"."vue-router": "VueRouter".vuex: "Vuex".axios: "axios"}}Copy the code

resolve


// Alias Settings
const webpackConfig  = {
  // ...
  resolve: {
    alias: {
      "@": resolve("src")},extensions: [".js".".vue"]}}Copy the code

devServer


// The development environment starts the service configuration
const webpackConfig = {
  devServer: {
    quiet: true.open:true.historyApiFallback: true.proxy: {
      "/api": "http://localhost:3000"
    },
    hot: true.contentBase: join(__dirname, ".. /dist/assets"),}}Copy the code

The above is the common configuration in Webpack development, more configuration and optimization please refer to the official website.

Refer to the article

Easy to understand Webpack

Please go to git repository to light up the little star to learn together and make progress together.