zoukankan      html  css  js  c++  java
  • 653 webpack中使用CDN、shimming,Hash、ContentHash、ChunkHash

    什么是CDN?


    购买CDN服务器


    第三方库的CDN服务器


    认识shimming【了解】


    Shimming预支全局变量


    MiniCssExtractPlugin


    目录结构


    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div id="app"></div>
      <div id="root"></div>
    
      <!-- 【开发环境下,不需要cdn】 -->
      <!-- ejs中的if判断 -->
      <% if (process.env.NODE_ENV === 'production') { %> 
      <script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
      <% } %> 
    </body>
    </html>
    

    main.js

    import _ from 'lodash';
    import dayjs from 'dayjs';
    
    import "./request";
    import "./style.css";
    
    console.log("Hello Main");
    console.log(_.join(["Hello", "Main"]));
    console.log(dayjs(), "Main");
    

    webpack.common.js

    const resolveApp = require("./paths");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const VueLoaderPlugin = require("vue-loader/lib/plugin");
    const TerserPlugin = require("terser-webpack-plugin");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const webpack = require('webpack');
    
    const { merge } = require("webpack-merge");
    
    const prodConfig = require("./webpack.prod");
    const devConfig = require("./webpack.dev");
    
    const commonConfig = (isProduction) => {
      return {
        // 【hash:多入口进行打包的时候,如果每一个地方发生变化,另一个文件也发生变化,就用hash】
        entry: {
          main: "./src/main.js",
          index: "./src/index.js"
          // main: { import: "./src/main.js", dependOn: "shared" },
          // index: { import: "./src/index.js", dependOn: "shared" },
          // lodash: "lodash",
          // dayjs: "dayjs"
          // shared: ["lodash", "dayjs"]
        },
        output: {
          path: resolveApp("./build"),
          filename: "js/[name].bundle.js",
          chunkFilename: "js/[name].[hash:6].chunk.js",
          publicPath: ""
        },
        resolve: {
          extensions: [".wasm", ".mjs", ".js", ".json", ".jsx", ".ts", ".vue"],
          alias: {
            "@": resolveApp("./src"),
            pages: resolveApp("./src/pages"),
          },
        },
        optimization: {
          // 对代码进行压缩相关的操作
          minimizer: [
            new TerserPlugin({
              extractComments: false,
            }),
          ],
          // natural: 使用自然数(不推荐),
          // named: 使用包所在目录作为name(在开发环境推荐)
          // deterministic: 生成id, 针对相同文件生成的id是不变
          // chunkIds: "deterministic",
          splitChunks: {
            // async异步导入
            // initial同步导入
            // all 异步/同步导入
            chunks: "all",
            // 最小尺寸: 如果拆分出来一个, 那么拆分出来的这个包的大小最小为minSize
            minSize: 20000,
            // 将大于maxSize的包, 拆分成不小于minSize的包
            maxSize: 20000,
            // minChunks表示引入的包, 至少被导入了几次
            minChunks: 1,
            cacheGroups: {
              vendor: {
                test: /[\/]node_modules[\/]/,
                filename: "js/[id]_vendors.js",
                // name: "vendor-chunks.js",
                priority: -10
              },
              // bar: {
              //   test: /bar_/,
              //   filename: "[id]_bar.js"
              // }
              default: {
                minChunks: 2,
                filename: "common_[id].js",
                priority: -20
              }
            }
          },
          // true/multiple
          // single
          // object: name
          runtimeChunk: {
            name: function(entrypoint) {
              return `why-${entrypoint.name}`
            }
          }
        },
        module: {
          rules: [
            {
              test: /.jsx?$/i,
              use: "babel-loader",
            },
            {
              test: /.vue$/i,
              use: "vue-loader",
            },
            {
              test: /.css/i,
              // style-lodader -> development,开发环境才需要 【生产环境用 MiniCssExtractPlugin.loader。】
              use: [
                isProduction ? MiniCssExtractPlugin.loader: "style-loader", 
                "css-loader"],
            },
          ],
        },
        plugins: [
          new HtmlWebpackPlugin({
            template: "./index.html",
          }),
          new VueLoaderPlugin(),
          // 当在代码中遇到某一个变量找不到时, 我们会通过ProvidePlugin, 自动导入对应的库
          // new webpack.ProvidePlugin({
          //   axios: "axios",
          //   get: ["axios", "get"]
          // })
        ],
      };
    }
    
    module.exports = function(env) {
      const isProduction = env.production;
      process.env.NODE_ENV = isProduction ? "production" : "development";
    
      const config = isProduction ? prodConfig : devConfig;
      const mergeConfig = merge(commonConfig(isProduction), config);
    
      return mergeConfig;
    };
    

    webpack.prod.js

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    const isProduction = true;
    
    module.exports = {
      mode: "production",
      externals: {
        // 包名: 全局对象,value写暴露出来的全局对象,比如window._ 、 window.dayjs
        lodash: "_", 
        dayjs: "dayjs" // window.dayjs
      },
      plugins: [
        // 生产环境
        new CleanWebpackPlugin({}),
        new MiniCssExtractPlugin({
          filename: "css/[name].[hash:8].css"
        })
      ]
    }
    

    webpack.dev.js

    const resolveApp = require('./paths');
    const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
    
    const isProduction = false;
    
    console.log("加载devConfig配置文件");
    
    module.exports = {
      mode: "development",
      devServer: {
        hot: true,
        hotOnly: true,
        compress: true,
        contentBase: resolveApp("./why"),
        watchContentBase: true,
        proxy: {
          "/why": {
            target: "http://localhost:8888",
            pathRewrite: {
              "^/why": ""
            },
            secure: false,
            changeOrigin: true
          }
        },
        historyApiFallback: {
          rewrites: [
            {from: /abc/, to: "/index.html"}
          ]
        }
      },
      plugins: [
        // 开发环境
        new ReactRefreshWebpackPlugin(),
      ]
    }
    

    Hash、ContentHash、ChunkHash


    目录结构


    main.js

    import "./style.css";
    
    console.log("indexaaaaaccccc");
    

    webpack.common.js

    const resolveApp = require("./paths");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const VueLoaderPlugin = require("../../19_webpack的DLL引入/config/node_modules/vue-loader/lib/plugin");
    const TerserPlugin = require("terser-webpack-plugin");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const webpack = require('webpack');
    
    const { merge } = require("webpack-merge");
    
    const prodConfig = require("./webpack.prod");
    const devConfig = require("./webpack.dev");
    
    const commonConfig = (isProduction) => {
      return {
        entry: {
          main: "./src/main.js",
          index: "./src/index.js"
          // main: { import: "./src/main.js", dependOn: "shared" },
          // index: { import: "./src/index.js", dependOn: "shared" },
          // lodash: "lodash",
          // dayjs: "dayjs"
          // shared: ["lodash", "dayjs"]
        },
        output: {
          path: resolveApp("./build"),
          filename: "js/[name].[chunkhash:6].bundle.js",
          chunkFilename: "js/[name].[contenthash:6].chunk.js",
          publicPath: ""
        },
        resolve: {
          extensions: [".wasm", ".mjs", ".js", ".json", ".jsx", ".ts", ".vue"],
          alias: {
            "@": resolveApp("./src"),
            pages: resolveApp("./src/pages"),
          },
        },
        optimization: {
          // 对代码进行压缩相关的操作
          minimizer: [
            new TerserPlugin({
              extractComments: false,
            }),
          ],
          // natural: 使用自然数(不推荐),
          // named: 使用包所在目录作为name(在开发环境推荐)
          // deterministic: 生成id, 针对相同文件生成的id是不变
          // chunkIds: "deterministic",
          splitChunks: {
            // async异步导入
            // initial同步导入
            // all 异步/同步导入
            chunks: "all",
            // 最小尺寸: 如果拆分出来一个, 那么拆分出来的这个包的大小最小为minSize
            minSize: 20000,
            // 将大于maxSize的包, 拆分成不小于minSize的包
            maxSize: 20000,
            // minChunks表示引入的包, 至少被导入了几次
            minChunks: 1,
            cacheGroups: {
              vendor: {
                test: /[\/]node_modules[\/]/,
                filename: "js/[id]_vendors.js",
                // name: "vendor-chunks.js",
                priority: -10
              },
              // bar: {
              //   test: /bar_/,
              //   filename: "[id]_bar.js"
              // }
              default: {
                minChunks: 2,
                filename: "common_[id].js",
                priority: -20
              }
            }
          },
          // true/multiple
          // single
          // object: name
          // runtimeChunk: {
          //   name: function(entrypoint) {
          //     return `why-${entrypoint.name}`
          //   }
          // }
        },
        module: {
          rules: [
            {
              test: /.jsx?$/i,
              use: "babel-loader",
            },
            {
              test: /.vue$/i,
              use: "vue-loader",
            },
            {
              test: /.css/i,
              // style-lodader -> development
              use: [
                isProduction ? MiniCssExtractPlugin.loader: "style-loader", 
                "css-loader"],
            },
          ],
        },
        plugins: [
          new HtmlWebpackPlugin({
            template: "./index.html",
          }),
          new VueLoaderPlugin(),
          // 当在代码中遇到某一个变量找不到时, 我们会通过ProvidePlugin, 自动导入对应的库
          // new webpack.ProvidePlugin({
          //   axios: "axios",
          //   get: ["axios", "get"]
          // })
        ],
      };
    }
    
    module.exports = function(env) {
      const isProduction = env.production;
      process.env.NODE_ENV = isProduction ? "production" : "development";
    
      const config = isProduction ? prodConfig : devConfig;
      const mergeConfig = merge(commonConfig(isProduction), config);
    
      return mergeConfig;
    };
    

    webpack.dev.js

    const resolveApp = require('./paths');
    const ReactRefreshWebpackPlugin = require('../../19_webpack的DLL引入/config/node_modules/@pmmmwh/react-refresh-webpack-plugin');
    
    const isProduction = false;
    
    console.log("加载devConfig配置文件");
    
    module.exports = {
      mode: "development",
      devServer: {
        hot: true,
        hotOnly: true,
        compress: true,
        contentBase: resolveApp("./why"),
        watchContentBase: true,
        proxy: {
          "/why": {
            target: "http://localhost:8888",
            pathRewrite: {
              "^/why": ""
            },
            secure: false,
            changeOrigin: true
          }
        },
        historyApiFallback: {
          rewrites: [
            {from: /abc/, to: "/index.html"}
          ]
        }
      },
      plugins: [
        // 开发环境
        new ReactRefreshWebpackPlugin(),
      ]
    }
    

    webpack.prod.js

    const { CleanWebpackPlugin } = require('../../19_webpack的DLL引入/config/node_modules/clean-webpack-plugin');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    const isProduction = true;
    
    module.exports = {
      mode: "production",
      externals: {
        lodash: "_",
        dayjs: "dayjs"
      },
      plugins: [
        // 生成环境
        new CleanWebpackPlugin({}),
        new MiniCssExtractPlugin({
          filename: "css/[name].[contenthash:6].css"
        })
      ]
    }
    

  • 相关阅读:
    【BZOJ1014】【JSOI2008】火星人prefix
    [agc011e]increasing numbers
    NOIp2018模拟赛四十一
    拉格朗日插值&&快速插值
    NOIp2018模拟赛四十
    (2016北京集训十四)【xsy1557】task
    (2016北京集训十四)【xsy1556】股神小D
    数据泵导入ORA-39082报错解决
    OracleDBA职责—备份与恢复技术—概念
    OracleDBA职责—备份与恢复技术—RMAN3
  • 原文地址:https://www.cnblogs.com/jianjie/p/14543120.html
Copyright © 2011-2022 走看看