Webpack(二十四):总结

webpack 基本配置

搭建准备

  • $ npm init -y
    • 创建 package.json
  • $ npm install webpack webpack-cli --save-dev
    • 安装基础依赖
  • $ npm i webpack-dev-server --save-dev
    • 配置开发环境的运行
  • 创建 webpack.config.js 配置文件
    • 构建webpack运行的默认配置文件
  • $ npm i html-loader html-webpack-plugin --save-dev
    • 生成一个HTML文件作为站点入口

基础运行配置

  • 目录结构
    .
    ├── public
    │   └── index.html          ## html模版文件
    ├── src
    │   ├── asset               ## 资源文件
    │   └── main.js             ## webpack入口文件
    ├── package.json            ## npm init
    └── webpack.config.js       ## webpack默认配置文件
    
  • webpack.config.js
    const {
           resolve} = require('path');
    
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
           
    
        /* 入口 */
        entry: [
            resolve(__dirname, 'src/main.js'),
        ],
    
        /* 插件 */
        plugins: [
    
            /* 生成一个HTML文件作为站点入口 */
            new HtmlWebpackPlugin({
           
                template: resolve(__dirname, 'public/index.html'),  // 模版html
            }),
    
        ],
    
        /* 模式 development || production */
        mode: "development",
    
        /* 开发环境服务 npx webpack-dev-server */
        devServer: {
           
            /* 内容地址 */
            contentBase: resolve(__dirname, 'dist'),
            /* 启动gzip压缩 */
            compress: true,
            /* 站点的端口号 */
            port: 3000,
            /* 执行后自动打开浏览器 */
            open: true,
        }
    
    };
    

打包样式资源

  • $ npm i style-loader css-loader less less-loader --save-dev
module.exports = {
     

    /* 配置loader */
    module: {
     

        /* 规则配置 默认从数组尾向前进行处理 */
        rules: [

            /* 处理css文件 style-loader, css-loader */
            {
     test: /\.css$/, use: ['style-loader', 'css-loader']},

            /* 处理less文件 style-loader, css-loader, less-loader */
            {
     test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},

        ],

    }

}

每次构建清空打包后目录文件夹

$ npm i clean-webpack-plugin --save-dev

const {
      CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
     

    plugins: [

        /* 每次构建清空打包后目录文件夹 */
        new CleanWebpackPlugin(),

    ]

}

webpack 之 entry

entry 三种格式

entry : String --> 单入口模式 (打包会生成一个chunk,输出一个bundle文件)

module.exports = {
     
    entry: './src/main.js'
}

entry : Array --> 多入口模式 (所有入口文件最终只会形成一个chunk,输出一个bundle文件)
一般会将html文件放入,使开发环境的HMR配置生效

module.exports = {
     
    entry: [ './src/main.js', './public/index.html', ],
}

entry : Object --> 多入口模式 (有几个入口文件最终就会形成几个chunk,chunk名称为key,同时也会输出几个bundle文件)

module.exports = {
     
    entry: {
     
        main: './src/main.js',
        demo: './src/views/demo.js',
    }
}

entry : Object[Array] --> 多入口模式 (数组部分打包成一个chunk,字符串部分打包成一个chunk)

 module.exports = {
     
     entry: {
     
         main: [ './src/main.js', './src/views/index.js' ],
         demo: './src/views/demo.js',
     }
 }

webpack 之 output

output 配置输出文件常用配置

module.exports = {
     

    /* 出口 */
    output: {
     

        /* 构建输出地址 绝对路径 */
        path: resolve(__dirname, 'dist'),

        /* 构建输出文件名称 注意:配置热更新hot后启动服务将无法使用contenthash作为文件名 */
        filename: this.mode === 'production' ? 'js/[name].[contenthash:10].js' : 'js/[name].[hash:10].js',

        /* 输出文件路径定义 一般用于生产环境 */
        publicPath: '/',

        /* 对非入口文件chunk创建名称 js代码采用import('./xxx/xxx.js').then().catch(); */
        chunkFilename: 'js/[name]_chunk.js',

        /* 将value作为打包后的全局变量暴露出来,默认用var定义 示例:var main = (function(modules) {···})({···}) */
        library: '[name]',

        /* 设置后默认值 var , 实现通过哪种(var, commonjs, window, global)方式定义暴露的变量 */
        libraryTarget: 'var', // var commonjs window global

    },

}

webpack 之 module

module 配置loader常用配置

module.exports = {
     
    /* 配置loader */
    module: {
     

        /* loader配置 默认从数组尾向前进行处理 */
        rules: [

            /* 处理css文件 style-loader, css-loader */
            {
     test: /\.css$/, use: ['style-loader', 'css-loader']},

            /* 处理less文件 style-loader, css-loader, less-loader */
            {
     test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},

            /* 处理html文件 html-loader 将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串 */
            {
     test: /\.html$/, loader: 'html-loader'},

        ],

    },
}

webapck 之 resolve

resolve --> alias: 解决引用文件时需要多层引入问题

  • 比如引用css文件:import '../../../../xxx/xxx/xxx.css';
/* main.js */
import '$css/common.css';
import '$css/demo.less';
/* webpack.config.js */
module.exports = {
     

    /* 解析模块的规则 */
    resolve: {
     

        /* 配置解析模块路径别名 */
        alias: {
     
            $css: resolve(__dirname, 'src/assets/css')
        }

    }

}

resolve --> extensions: 配置省略文件路径后缀名

/* main.js */
import './css/xxx'; // 省略 .css
import './json/xxx'; // 省略 .json
import './js/xxx'; // 省略 .js
/* webpack.config.js */
module.exports = {
     

    /* 解析模块的规则 */
    resolve: {
     

        /* 配置省略文件路径后缀名 (先会去查找.js文件,有就返回,没有继续向后查找) */
        extensions: [ '.js', '.json', '.css']

    }

}

resolve --> modules: 配置解析模块(node_modules)寻找地址

module.exports = {
     
    /* 解析模块的规则 */
    resolve: {
     
        /* 配置解析模块(node_modules)寻找地址 (默认在webpack.config.js所在目录向上寻找) */
        modules: [ resolve(__dirname, 'node_modules'), 'node_modules' ], // 数组[1]预防之前配置寻找不到node_modules而配置
    
    }
}

webpack 之 devServer

devServer 用于开发环境

module.exports = {
     
    /* npx webpack-dev-server */
    devServer: {
     
        /* 内容地址 */
        contentBase: resolve(__dirname, 'dist'),
        /* 监视 contentBase 下的所有文件,一旦文件产生变化就会reload刷新 */
        watchContentBase: true,
        /* 监视配置 */
        watchOptions: {
     
            /* 忽略 node_modules 下文件 */
            ignored: /node_modules/
        },
        /* 启动gzip压缩 */
        compress: true,
        /* 站点的端口号 */
        port: 3000,
        /* 域名 */
        host: 'localhost',
        /* 执行后自动打开浏览器 */
        open: true,
        /* 热更新 */
        hot: true,
        /* 不需要打印启动程序时的日志信息 */
        clientLogLevel: false,
        /* 除了一些基本启动信息以外,其他内容不需要打印 */
        quiet: true,
        /* 如果出错了,不需要全屏提示 */
        overlay: false,
        /* 服务器代理 --> 解决开发环境跨域问题 */
        proxy: {
     
            /* 接收到/api/xxx的请求后,会将请求转发到http://localhost:3000这个地址下,从而解决跨域 */
            '/api': {
     
                target: 'http://localhost:3000',
                /* 路径重写 将请求路径 /api/xxx 改写成 /xxx (去掉 /api ) */
                pathRewrite: {
     
                    '^/api': ''
                }
            }
        }
    },
}

webpack 之 optimization

splitChunks 默认配置

module.exports = {
     
    mode: 'production',
    /* 优化 mode: 'production' */
    optimization: {
     
        /* chunk分割 */
        splitChunks: {
     
            chunks: 'all',
            /* ========================以下为默认配置项,可以不写========================= */
            /* 分割的chunk最小为30kb */
            minSize: 30 * 1024,
            /* 分割的chunk最大无限制 */
            maxSize: 0,
            /* 提取的chunk最少被引用1次 */
            minChunks: 1,
            /* 按需加载时并行加载的文件最大数量 */
            maxAsyncRequests: 5,
            /* 入口js文件最大并行请求数量 */
            maxInitialRequests: 3,
            /* 名称连接符 */
            automaticNameDelimiter: '~',
            /* 可以使用命名规则 */
            name: true,
            /* 分割chunk的组 */
            cacheGroups: {
     
                /* node_modules中的文件会被打包到vendors组的chunk中, 名称:vendors~xxx.js */
                vendors: {
     
                    test: /[\\/]node_modules[\\/]/,
                    /* 优先级 */
                    priority: -10,
                },
                default: {
     
                    /* 提取的chunk最少被引用2次 */
                    minChunks: 2,
                    priority: -20,
                    /* 如果当前要打包的模块和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块,比如都引入了jQuery */
                    reuseExistingChunk: true,
                }
            }
        }
    }
}

splitChunks 默认配置 出现的问题

// main.js
import(/* webpackChunkName: 'index' */ './views/index')
    .then(res=>{
     
        console.log(res);
    })
    .catch(err=>{
     
        console.log(err);
    });

// index.js
console.log('Index Js'); 
// => 修改为
// console.log('Index Js ABC'); 

// webpack.config.js
module.exports = {
     
    mode: 'production',
    /* 优化 mode: 'production' */
    optimization: {
     
        /* chunk分割 */
        splitChunks: {
     
            chunks: 'all',
        }
    }
}

当其中index.js的代码进行修改后,
预期希望打包后只有index.js的文件名发生变化,不会影响到main.js的缓存机制,
但是由于main.js代码内部存储了index.js文件的hash值,
最终导致index.js被修改后再次打包main.js和index.js的文件名都发生了变化,
导致main.js文件没有从缓存中读取,又请求了一次,影响性能

Webpack(二十四):总结_第1张图片

以上问题解决方法

希望提取出main.js中引用的index.js的hash值在进行单独处理

// webpack.config.js
module.exports = {
     
    mode: 'production',
    /* 优化 mode: 'production' */
    optimization: {
     
        /* chunk分割 */
        splitChunks: {
     
            chunks: 'all',
        }
    },
    /* 将当前模块记录的其他模块的hash值单独打包成一个文件 runtime */
    runtimeChunk: {
     
        name: entrypoint => `runtime-${
       entrypoint.name}`
    }
}

Webpack(二十四):总结_第2张图片

minimizer 配置生产环境的压缩方案 js和css方案

  • 需要安装:$ npm i terser-webpack-plugin --save-dev
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
     
    optimization: {
     
        /* 配置生产环境的压缩方案 js和css方案 */
        minimizer: [
            new TerserPlugin({
     
                /* 开启缓存 */
                cache: true,
                /* 开启多进程打包 */
                parallel: true,
                /* 启用 source-map */
                sourceMap: true,
            }),
        ]
    }
}

完整代码

Webpack(二十四):总结_第3张图片

npm i html-loader --save-dev
npm i terser-webpack-plugin --save-dev
npm i clean-webpack-plugin --save-dev
npm i style-loader css-loader less less-loader --save-dev
npm i html-webpack-plugin --save-dev
npm i webpack-dev-server --save-dev
npm i webpack webpack-cli --save-dev
{
     
  "name": "javascriptdesignpatterns",
  "version": "1.0.0",
  "description": "设计模式",
  "main": "index.js",
  "scripts": {
     
    "dev": "npx webpack-dev-server",
    "build": "webpack"
  },
  "author": "ProsperLee",
  "license": "ISC",
  "devDependencies": {
     
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^4.3.0",
    "html-loader": "^1.3.2",
    "html-webpack-plugin": "^4.5.0",
    "less": "^3.12.2",
    "less-loader": "^7.0.2",
    "style-loader": "^2.0.0",
    "terser-webpack-plugin": "^4.2.3",
    "webpack": "^4.44.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}
// webpack.config.js
const {
     resolve} = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');

const {
      CleanWebpackPlugin } = require('clean-webpack-plugin');

const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
     

    /* 入口 */
    entry: [

        './src/main.js',

        './public/index.html',

    ],

    /* 出口 */
    output: {
     

        /* 构建输出地址 绝对路径 */
        path: resolve(__dirname, 'dist'),

        /* 构建输出文件名称 注意:配置热更新hot后启动服务将无法使用contenthash作为文件名 */
        filename: this.mode === 'production' ? 'js/[name].[contenthash:10].js' : 'js/[name].[hash:10].js',

        /* 输出文件路径定义 一般用于生产环境 */
        publicPath: '/',

        /* 对非入口文件chunk创建名称 */
        chunkFilename: 'js/[name].[contenthash:10]_chunk.js',

        /* 将value作为打包后的全局变量暴露出来,默认用var定义 示例:var main = (function(modules) {···})({···}) */
        library: '[name]',

        /* 设置后默认值 var , 实现通过哪种(var, commonjs, window, global)方式定义暴露的变量 */
        libraryTarget: 'var', // var commonjs window global

    },

    /* 配置loader */
    module: {
     

        /* loader配置 默认从数组尾向前进行处理 */
        rules: [

            /* 处理css文件 style-loader, css-loader */
            {
     test: /\.css$/, use: ['style-loader', 'css-loader']},

            /* 处理less文件 style-loader, css-loader, less-loader */
            {
     test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},

            /* 处理html文件 html-loader 将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串 */
            {
     test: /\.html$/, loader: 'html-loader'},

        ],

    },

    /* 插件 */
    plugins: [

        /* 每次构建清空打包后目录文件夹 */
        new CleanWebpackPlugin(),

        /* 生成一个HTML文件作为站点入口 */
        new HtmlWebpackPlugin({
     
            template: resolve(__dirname, 'public/index.html'),  // 模版html
            minify: true, // 是否压缩
        }),

    ],

    /* 模式 development || production */
    mode: 'development',

    /* npx webpack-dev-server */
    devServer: {
     
        /* 内容地址 */
        contentBase: resolve(__dirname, 'dist'),
        /* 监视 contentBase 下的所有文件,一旦文件产生变化就会reload刷新 */
        watchContentBase: true,
        /* 监视配置 */
        watchOptions: {
     
            /* 忽略 node_modules 下文件 */
            ignored: /node_modules/
        },
        /* 启动gzip压缩 */
        compress: true,
        /* 站点的端口号 */
        port: 3000,
        /* 域名 */
        host: 'localhost',
        /* 执行后自动打开浏览器 */
        open: true,
        /* 热更新 */
        hot: true,
        /* 不需要打印启动程序时的日志信息 */
        clientLogLevel: false,
        /* 除了一些基本启动信息以外,其他内容不需要打印 */
        quiet: true,
        /* 如果出错了,不需要全屏提示 */
        overlay: false,
        /* 服务器代理 --> 解决开发环境跨域问题 */
        proxy: {
     
            /* 接收到/api/xxx的请求后,会将请求转发到http://localhost:3000这个地址下,从而解决跨域 */
            '/api': {
     
                target: 'http://localhost:3000',
                /* 路径重写 将请求路径 /api/xxx 改写成 /xxx (去掉 /api ) */
                pathRewrite: {
     
                    '^/api': ''
                }
            }
        }
    },

    /* 开启调试功能 */
    devtool: 'eval-source-map',

    /* 解析模块的规则 */
    resolve: {
     

        /* 配置解析模块路径别名 */
        alias: {
     
            $css: resolve(__dirname, 'src/assets/css')
        },

        /* 配置省略文件路径后缀名 (先会去查找.js文件,有就返回,没有继续向后查找) */
        extensions: [ '.js', '.json', '.css'],

        /* 配置解析模块(node_modules)寻找地址 (默认在webpack.config.js所在目录向上寻找) */
        modules: [ resolve(__dirname, 'node_modules'), 'node_modules' ], // 数组[1]预防之前配置寻找不到node_modules而配置

    },

    /* 优化 mode: 'production' */
    optimization: {
     

        /* chunk分割 */
        splitChunks: {
     
            chunks: 'all',
            // /* 分割的chunk最小为30kb */
            // minSize: 30 * 1024,
            // /* 分割的chunk最大无限制 */
            // maxSize: 0,
            // /* 提取的chunk最少被引用1次 */
            // minChunks: 1,
            // /* 按需加载时并行加载的文件最大数量 */
            // maxAsyncRequests: 5,
            // /* 入口js文件最大并行请求数量 */
            // maxInitialRequests: 3,
            // /* 名称连接符 */
            // automaticNameDelimiter: '~',
            // /* 可以使用命名规则 */
            // name: true,
            // /* 分割chunk的组 */
            // cacheGroups: {
     
            //     /* node_modules中的文件会被打包到vendors组的chunk中, 名称:vendors~xxx.js */
            //     vendors: {
     
            //         test: /[\\/]node_modules[\\/]/,
            //         /* 优先级 */
            //         priority: -10,
            //     },
            //     default: {
     
            //         /* 提取的chunk最少被引用2次 */
            //         minChunks: 2,
            //         priority: -20,
            //         /* 如果当前要打包的模块和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块,比如都引入了jQuery */
            //         reuseExistingChunk: true,
            //     }
            // }
        },

        /* 将当前模块记录的其他模块的hash值单独打包成一个文件 runtime */
        runtimeChunk: {
     
            name: entrypoint => `runtime-${
       entrypoint.name}`
        },

        /* 配置生产环境的压缩方案 js和css方案 */
        minimizer: [
            new TerserPlugin({
     
                /* 开启缓存 */
                cache: true,
                /* 开启多进程打包 */
                parallel: true,
                /* 启用 source-map */
                sourceMap: true,
            }),
        ],

    }

};

你可能感兴趣的:(#,Webpack,webpack)