What are automated build tools

In ordinary code development, the language tools we use are too complex to be recognized by the browser. At this time, we need to carry out a series of transformations to the code we write and then execute it through the browser. The transformation tools are called automatic build tools. Of course, automation tools have more advantages than that. They also help optimize and compress code.

Gulp

Since I seldom use gulp, I will not introduce it here. Here is a template made by combining gulp with common plugins. For more information, please refer to the official website and templates

// Implement the build task for this project
const { series, parallel, src, dest, watch } = require('gulp')
NPM install --global --production Windows-build-tools
// If not: NPM install --global node-gyp
const sass = require('gulp-sass')
const babel = require('gulp-babel')
const swig = require('gulp-swig')
const browserSync = require('browser-sync')
const imagemin = require('gulp-imagemin')
const del = require('del')
const loadPlugins = require('gulp-load-plugins')
// This plugins contains many glUP plugins for plugins.xxx to use in this way
const plugins = loadPlugins()
const bs = browserSync.create()

// The configuration of the packaged HTML
// will replace the template file
const data = {
    // Use {{date}} in HTML
    date: new Date()}Clean up your files before packing them
const clean = () = > {
    return del(['dist'.'temp'])}// To compile SCSS files into CSS, install gulp-sass
const style = () = > {
    return src('src/assets/styles/*.scss', { base: 'src' })
        .pipe(sass())
        // Pack to temp because it needs to be compressed
        .pipe(dest('dist'))
        // Indicates that hot updates will be sent to the server for use
        .pipe(bs.reload({ stream: true}}))// Package the js file
// Gulp-babel@babel/core@babel /preset-env needs to be installed
const script = () = > {
    return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(babel({ presets: ['@babel/preset-env']}))// Pack to temp because it needs to be compressed
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))// Package the HTML file
Gulp-swig needs to be installed
const page = () = > {
    return src('src/*.html', { base: 'src' })
        .pipe(swig({
            data,
            // Prevent pages from being updated due to template caching
            defaults: { cache: false}}))// Pack to temp because it needs to be compressed
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}}))// Package image files and font files
// Install gulp-imagemin
const image = () = > {
    return src('src/assets/images/**', { base: 'src' })
        .pipe(imagemin())
        .pipe(dest('dist'))}const font = () = > {
    return src('src/assets/fonts/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))}// The server starts
const serve = () = > {
    // Observe and heat update
    watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)

    watch([
        'src/assets/images/**'.'src/assets/fonts/**'.'public/**'
    ], bs.reload)

    bs.init({
        notify: false.port: 2080.// open: false,
        // files: 'dist/**',
        server: {
            // Based on the basic path
            baseDir: ['temp'.'src'.'public'].routes: {
                // Node_modules will be replaced when HTML uses /node_modules
                '/node_modules': 'node_modules'}}})}// This is mainly to compress the packaged code
// Gulp-xxx hump is converted to underscore /:cleanCss <=> gulp-clean-css
const useref = () = > {
    return src('temp/*.html', { base: 'temp' })
        // Compressed temp files
        .pipe(plugins.useref({ searchPath: ['temp'.'. ']}))// Compress as required
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
            // Filter whitespace characters
            collapseWhitespace: true.// Compress the CSS
            minifyCSS: true.// Compress js
            minifyJS: true
        })))
        .pipe(dest('dist'))}// Output static files in public
const extra = () = > {
    return src('public/**', { base: 'public' })
        .pipe(dest('dist'))}// Both server startup and packaging require packaging of these three things
const compile = parallel(style, script, page)

// series indicates synchronous wait execution, parallel indicates asynchronous execution
const build = series(
    clean,
    parallel(
        series(compile, useref),
        image,
        font,
        extra
    )
)


const develop = series(compile, serve)

// Use gulp build or gulp develop
module.exports = {
    build,
    develop
}
Copy the code

Webpack

Webpack is currently one of the most mainstream packaging tools. Can help us to file JS compression, CSS compression, template file compilation and so on, so as to reduce the front-end workload.

Below is a webpack template that can be created automatically by downloading the webpack plug-in in vscode.

const path = require('path');
module.exports = {
  // Development mode: Different development and Production modes have different optimizations for different scenarios
  mode: 'development'.// Import file
  entry: path.join(__dirname, 'src'.'index'),
  // Output file
  output: {
    path: path.join(__dirname, 'dist'),
    filename: "bundle.js",},// Module contains many loaders
  // loader is used to convert files
  module: {
    rules: [{
      test: /.jsx? $/,
      include: [
        path.resolve(__dirname, 'src')].exclude: [
        path.resolve(__dirname, 'node_modules')].loader: 'babel-loader'.query: {
        presets: [["@babel/env", {
            "targets": {
              "browsers": "last 2 chrome versions"}}]]}}, {loader: './my-loader'}},// File suffixes are introduced by default
  resolve: {
    extensions: ['.json'.'.js'.'.jsx']},devtool: 'source-map'.devServer: {
    contentBase: path.join(__dirname, '/dist/'),
    inline: true.host: 'localhost'.port: 8080,}};Copy the code

Loader

The main function of loader in Webpack is to convert the input file to the output file

const path = require("path");
module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",},module: {
        rules: [{// Only files ending in js are matched
                test: /.js$/.// Here we create a custom loader in the current folder
                loader: "./my-loader",},],},};Copy the code

Here is the content of our my-loader

module.exports = function(source) {
    // source is the content of the original file
    console.log('run loader')
    // Return the contents of the modified file, which must be the contents of the JS file
    return source;
};
Copy the code

As you can see, we can perform a series of transformations on the matching input file and then return it. This is how loader works in WebPack. Normally we don’t write the loader ourselves and use an off-the-shelf one.

const path = require("path");
module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",},module: {
        // These two loaders allow WebPack to convert CSS files
        NPM install style-loader CSS-loader --save-dev
        rules: [{test: /\.css$/,
                use: ["style-loader"."css-loader"],},],},};Copy the code

Plugin

Plug-ins in WebPack are primarily used to operate on various parts of the WebPack execution lifecycle. Here is a simple plugin example.

const path = require("path");

class MyPlugin {
  constructor (options) {
    console.log('my pulgin', options)
  }
  
  apply (compiler) {
    // You can call different hooks to execute code at different times
    / / hook API: https://www.webpackjs.com/api/compiler-hooks/#done
    compiler.plugin('entryOption'.compilation= > {
      console.log('hhah')}}}module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",},plugins: [new MyPlugin()]
};
Copy the code

It is common to use an existing plugin rather than write your own

SourceMap

Because packaged files are not easy to read, debugging errors can be troublesome. In this case, the source map is used to locate the compiled file to its original location. There are seven different mapping modes in Webpack. For details, visit the WebPack website. In general, development environments can use cheap-module-eval-source-map, while production environments do not require source map

module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    devtool: 'cheap-module-eval-source-map'};Copy the code

DevServer

Webpack-dev-server can be used to develop applications quickly, eliminating the need to compile them again every time the code changes

npm i webpack-dev-server --save

module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    // 之后启动可以npx webpack-dev-server
    devServer: {
        // Used to tell the server static access location
        contentBase: "./public".// Enable hot module replacement. CSS changes can be made without a page refresh
        // If you want js to do hot module replacement, you need to write logic in the code
        hot: true.// The proxy can be configured to access resources across domains
        proxy: {
            "/api": {
                target: "https://api.github.com",},},},};Copy the code

If you want to add hot module replacement to your JS code as well

 if (module.hot) {
     module.hot.accept('module_url'.function() {
         // The logic that needs to be done})}Copy the code

To distinguish the environment

Install built-in merge files

npm i webpack-merge --save

Create three configuration files

Common configuration: webpack.common.js

Development environment configuration: webpack.dev.js

Production environment configuration: webpack.prod.js

// webpack.common.js
const path = require("path");

module.exports = {
    entry: path.join(__dirname, "src"."index"),};// webpack.dev.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common");

module.exports = merge(common, {
    mode: "development"});// webpack.prod.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common");

module.exports = merge(common, {
    mode: "production"});Copy the code

Then execute different code logic NPX webpack –config webpack.prod.js according to different configuration files

tree shaking

Open/tree shaking ((webpack.docschina.org/guides/tree…

const path = require("path");
module.exports = {
    mode: "development".entry: path.join(__dirname, "src"."index"),
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",},// Use es module only
    optimization: {
        // The built-in export function is called after the export part is used
        usedExports: true.// Only the exported content used is packaged and optimized for variables
        minimize: true.// It is packaged as a function
        // concatenateModules: true,
        // Do not remove the side effect function
        // Need to set in package.json: "sideEffects": [" SRC /*.js"],
        // sideEffects: true,
    },
    devtool: 'source-map'};Copy the code

See the official website or this website for more features

Rollup

Compared to WebPack,Rollup is much lighter and doesn’t have as much functionality as WebPack, just packaging. So in the selection, WebPack is more suitable for web development and Rollup is more suitable for internal library development.

Here is a simple example

// rollup.config.js
import json from 'rollup-plugin-json';

export default {
  input: 'src/index.js'.output: {
    file: 'bundle.js'.format: 'cjs'
  },
  // Convert strings to JSON using json plugins
  plugins: [ json() ]
};
Copy the code

Packaged file

import * as config from '.. /package.json'
console.log(config.version)
Copy the code

The packaged file is much simpler than the webPack packaged file

'use strict';

var version = "1.0.0";

console.log(version);
Copy the code