20230418----重返学习-模块化开发-webpack打包

本文介绍了模块化开发的概念,包括单例模式、AMD和CMD的区别以及ES6的Module规范。接着详细讲解了Webpack的安装、配置和打包过程,包括如何配置开发服务器实现热更新和代理,以及使用CleanWebpackPlugin清除旧文件。此外,还提到了不同环境的配置和脚本命令的使用。
摘要由CSDN通过智能技术生成

day-052-fifty-two-20230418-模块化开发-webpack打包

模块化开发

  • 用于确保文件引入的顺序

单例设计模式

  • 单例设计模式:如果有多个模块,模块之间存在依赖关系,那我们在html中导入js的时候,我们需要注意模块之间的依赖关系【模块依赖关系越复杂,就会变得很恶心】

    • 例子

      • ./index.html

        <!DOCTYPE html>
        <html lang="en">
        <head>
          <meta charset="UTF-8">
        </head>
        <body>
          <h1>11111</h1>
          <script src="./ModelA.js"></script>
          <script src="./ModelB.js"></script>
          <script src="./index.js"></script>
        </body>
        </html>
        
      • ./ModelA.js

        let ModelA = (() => {
          //求和
          const sum = function sum(...args) {
            return args.reduce((res, item) => res + item, 0);
          };
          return {
            sum,
          };
        })();
        
      • ./ModelB.js

        let ModelB = (() => {
          //求平均值
          const average = function average(...args) {
            let sum = ModelA.sum(...args);
            return sum / args.length;
          };
          return {
            average,
          };
        })();
        
      • ./index.js

        // console.log(`ModelA-->`, ModelA);
        console.log(`ModelA.sum(1,2,3,4,5,6,7)-->`, ModelA.sum(1, 2, 3, 4, 5, 6, 7));
        console.log(`ModelB.average(1,2,3,4,5,6,7)-->`, ModelB.average(1, 2, 3, 4, 5, 6, 7));
        
    • 优点

      • 兼容性好
      • 依赖关系简单
  • 普通的script标签导入关系,只适合做简单的依赖关系,复杂的如相互循环关系不行

    A B C
    B依赖A
    C依赖B和A
    
      <script src="./ModelA.js"></script>
      <script src="./ModelB.js"></script>
      <script src="./index.js"></script>
    
    • 如:

      A B C D
      B依赖A和C
      C依赖A和D
      D依赖B和C
      

AMD(require.js)

AMD是依赖于require.js的写法,不过目前2023年差不多被淘汰了。

  • AMD思想,是在单例模式的基础上,实现了依赖的管控【管控模式:依赖前置 在具体开发模块代码之前,把所有需要的依赖先处理好,再去开发】

    • 依赖于其它模块并导出当前模块

      define(['A', 'B'], function (A, B) {
        'use strict';
        return {
          
        }
      });
      
  • grunt、glup、fis都是基于AMD思想开发的

  • 例子:

  • ./index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
    </head>
    <body>
      <h1>AMD</h1>
      <script src="./require.min.js"></script>
      <script src="./index.js"></script>
    </body>
    </html>
    
  • ./ModelA.js

    //导出文件--模块A不依赖于其它模块
    define(function (require, factory) {
      "use strict";
      return {
        sum(...args) {
          return args.reduce((res, item) => res + item, 0);
        },
      };
    });
    
  • ./ModelB.js

    //导出文件--模块B依赖于模块A
    define(["ModelA"], function (ModelA) {
      return {
        average(...args) {
          let sum = ModelA.sum(...args);
          return sum / args.length;
        },
      };
    });
    
  • ./index.js

    //导入文件,依赖于模块A与模块B
    require(["ModelA", "ModelB"], function (ModelA, ModelB) {
      console.log(`ModelA-->`, ModelA);
      console.log(`ModelA.sum(1,2,3,4,5)-->`, ModelA.sum(1, 2, 3, 4, 5));
      console.log(`ModelB.average(1,2,3,4,5)-->`, ModelB.average(1, 2, 3, 4, 5));
    });
    

CMD

  • CMD解决了前置依赖的问题CommonJS(后台–nodejs)/sea.js(前端)
  • nodejs --> 前端的JavaScript
    • 基本上支持所有的JavaScript的语法
    • 命令提示符(黑框) --> node XXX.js
  • node写法
    • ./ModelA.js

      //导出 单个值
      module.exports = function sum(...args) {
        return args.reduce((res, item) => res + item, 0);
      };
      
    • ./ModelB.js

      let sum = require("./ModelA");
      
      function average(...args) {
        let res = sum(...args);
        return res / args.length;
      }
      let num = 100;
      
      //导出,导出多个内容
      module.exports = {
        average,
        num,
      };
      
    • ./index.js

      // console.log(`111-->`, 111);
      
      let path = require("path"); //node.js自身的模块
      //导入,可以省略`.js`后缀,不能省略`./`(自己创建的模块);不加`./`,默认是node.js自己的模块。
      // 导入单个内容
      let sum = require("./ModelA");
      console.log(`sum-->`, sum);//sum--> [Function: sum]
      console.log(`sum(1,2,3,4,5)-->`, sum(1, 2, 3, 4, 5));//sum(1,2,3,4,5)--> 15
      
      // 导入多个内容
      // let ModelB=require('./ModelB')
      // console.log(`ModelB-->`, ModelB);
      
      // 导入多个内容,可以使用解构赋值
      let { average, num } = require("./ModelB");
      console.log(`average(1,2,3,4,5)-->`, average(1, 2, 3, 4, 5));//average(1,2,3,4,5)--> 3
      console.log(`num-->`, num);//num--> 100
      
    • 要用node.js中的node xxx命令来执行,这里在index.js所在目录中使用node index.js来调用。

ES6中的Module

  1. 在script标签中设置type=“module”,可以直接在浏览器端开启ES6Module规范,并且需要保证页面是基于HTTP/HTTPS协议预览–即本地开发要使用类似于Live Server的本地服务器

    <script type="module" src="main.js"></script>
    
  2. ES6Module规范

    1. 模块中只想导出一次,直接基于 export default 导出即可

      • 导出:

        export default sum; 
        export default {sum:sum};  
        
      • 导入:

        import sum from './A';
        
        import A from './A';  //=> A.sum(); 
        
      • 不能直接给A解构赋值import {sum} from './A';这样报语法错误

    2. 模块中想导出多次,导出多个方法(或者变量)给外面用 export

      • 导出:export {sum}; 直接导出对象是不支持的,或者obj={},我们export obj这样也不支持,像这样做需要使用 export default 处理

        export let num = 10;
        export function fn() {};
        
      • 导入:import A from './A'; 这样写也是不行的,这种方式只支持 export default

        import {num,fn} from './A';
        import * as C from './C.js';   => C.fn();
        
    3. 原理:浏览器底层机制,ES6中模块导出是按照导出一个对象处理的

      • 基于export导出的时候,浏览器底层机制,是按照导出一个对象处理的,每一次调用,都是设置为一个键值对。
        • import {num,fn} from './A',导出语句如果遇到了花括号,后面导出的值就是导出对象
        • import * as ModelA from './A',导出语句如果遇到了*号,后面导出的值就是导出对象,as表示设置别名。
      • 基于export default导出的东西,是赋值给导出对象default属性的。
        • import ModelA from './A',导出语句如果没遇到花括号,后面导出的值就是导出对象.default
     {
        // 基于 export 导出的内容,直接设置为键值对 
        num:10,
        fn(){},
        
        // 基于 export default 导出的东西,是赋值给对象的default属性的
        default:xxx
     }
    
    • 所以,当我们基于import的时候,如果后面是一个花括号的形式,就意为解构赋值,就是对整个模块进行解构。而如果是一个对象时,就意为接收了模块.default这个属性。
      1. 为啥 export default 导出的不能直接结构赋值?

        • 因为它导出的内容,在对象的default属性中,我们需要先拿到default属性的值,才能解构处理…

          import A from './A';  //->  会默认让 A=`对象.default `
          let {sum} = A;
          
      2. 为啥 export 导出的可以解构赋值?

        • 因为它是直接把内容付给对象的键值对,导入的时候直接解构即可…
      3. import * as X from ‘./A’; 此时它会把导出的对象赋值给X

  • 例子:
    • ./index.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
      </head>
      <body>
        <h1>ES6 Module</h1>
        <script type="module" src="./index.js"></script>
      </body>
      </html>
      
    • ./index.js

      //不可以省略后缀.js
      // import ModelA from "./ModelA.js";
      // console.log(`ModelA-->`, ModelA);
      
      //注意 `export default`导出的不能直接解构赋值,但可以用一个变量A接收之后再另起一行对变量A进行解构。
      //是因为底层对`export default`导出的东西放在`{default:{}}`中的`default属性`里了。
      // import {sum,num} from "./ModelA.js";
      // console.log(`num-->`, num);
      
      
      import {default as theDefault} from "./ModelA.js"
      console.log(`theDefault-->`, theDefault);
      // import {'default':{sum,num}} from "./ModelA.js"//default是关键字,会报错
      // console.log(`theDefault-->`, theDefault);
      
      // import ModelA from "./ModelA.js";
      // console.log(`ModelA-->`, ModelA);
      // let { sum, num } = ModelA;
      // console.log(`num-->`, num);
      
      import { average } from "./ModelB.js";
      console.log(`average-->`, average);
      
      // import { a, b, c } from "./ModelC.js";
      // console.log(`a, b, c-->`, a, b, c);
      
      //*表示导入全部,as表示起个别名
      import * as ModelC from "./ModelC.js";//代码运行的时候,import会自动提升到顶部,所以随意写位置都可以。
      console.log(`ModelC.a, ModelC.b, ModelC.c-->`, ModelC.a, ModelC.b, ModelC.c);
      
    • ./ModelA.js

      //单个导出---一个js文件可以出现多次
      // export
      
      // 多个导出--一个js文件只能出现一次
      // export default
      
      const sum = function sum(...args) {
        return args.reduce((res, item) => res + item, 0);
      };
      let num = 100;
      export default {
        sum,
        num,
      };
      
      
    • ./ModelB.js

      import ModelA from "./ModelA.js";
      
      export function average(...args) {
        let sum = modelA.sum(...args);
        return sum / args.length;
      }
      
      
    • ./ModelC.js

      export const a = 100;
      export const b = 200;
      export const c = 300;
      
      // 可以声明变量,值为对象
      export const obj = {
        n: 100,
        m: 200,
      };
      
      // export不能直接导出对象
      // export {
      //   nn:100,
      //   mm:200
      // }
      // 能直接导出对象的是`export default`
      export default {
        nn: 100,
        mm: 200,
      };
      // `export default`可以与`export`共存,但不能出现多次,即整个js文件中只能出现一次`export default`。
      

webpack打包

  1. 安装webpack

    1. 本地安装

      npm i webpack@5.49.0 webpack-cli@4.7.2
      
      • 好处:不同的文件夹可以安装不同的版本,一般就本地安装

      • 本地安装之后使用的方法

        • *方法1:

          1. 找到 package.json —> “scripts” 配置脚本命令

            • 名称可以自定义
            {
              "scripts": {
                "自定义脚本命令":"webpack"
              }
            }
            
          2. 在对应目录中执行配置的脚本命令

            npm run 自定义脚本命令
            // npm run serve//如果package.json中的"scripts"配置的scripts下的属性名称为serve
            
        • *方法2:

          1. 在对应目录中执行配置的脚本命令npx webpack (webpack5版本及以上)

            npx webpack
            
      • 默认打包的js是src目录下index.js为入口文件----》dist文件夹main.js为打包后的出口文件

    2. 全局安装

      npm i webpack@5.49.0 webpack-cli@4.7.2 -g    //安装
      npm uni webpack@5.49.0 webpack-cli@4.7.2 -g  //删除
      
      • 缺点:只能安装某一个版本

      • 全局安装之后可以在全局环境中的命令终端中使用命令 webpack

        webpack    //webpack执行
        
    • webpack一般要高一个版本,webpack-cli一般要低一个版本。如果相同版本,一般会报兼容性错误。
  2. 使用webpack

    • 本地安装之后使用的方法

      • *方法1:

        1. 找到 package.json —> “scripts” 配置脚本命令

          • 名称可以自定义
          {
            "scripts": {
              "自定义脚本命令":"webpack"
            }
          }
          
        2. 在对应目录中执行配置的脚本命令

          npm run 自定义脚本命令
          // npm run serve//如果package.json中的"scripts"配置的scripts下的属性名称为serve
          
      • *方法2:

        1. 在对应目录中执行配置的脚本命令npx webpack (webpack5版本及以上)

          npx webpack
          
    • 默认打包的js是src目录下index.js为入口文件----》dist文件夹main.js为打包后的出口文件

    • webpack 支持默认配置打包:不需要自己写配置项,它默认有自己的配置项,当我们执行 webpack 的时候,会按照默认配置项打包

      • 找到当前项目目录中的 src文件夹,找到文件夹中的index.js文件,作为入口,按照入口文件夹中的代码和模块依赖,最后进行打包,打包后的文件,放在dist目录中
  3. 自定义webpack打包的规则

    • 自己配置webpack的配置文件。如设置入口与出口

      1. 在根目录中新建 webpack.config.js
        • 当我们执行webpack命令的时候,首先检测有没有这个文件。

          • 有,就按照这个文件提供的规则进行打包编译;
          • 没有,就按照默认的规则进行打包编译。
        • 简单的配置项示例

          const path = require("path"); //node.js的路径模块
          
          module.exports = {
            entry: "./src/index.js", //入口文件路径
          
            //出口相关配置
            output: {
              filename: "index.js", //文件名称
              path: path.resolve(__dirname, "dist"), //在当前项目的根目录下,创建一个dist文件夹。
            },
          
            mode: "development", //development 开发环境-文件不会压缩,production 生产环境-会压缩
          };
          
          • 实际意思,该文件是一个js文件,以node.js的方式来执行。通过module.exports抛出一个表示webpack配置对象的对象。
            • 由于是node.js的文件,故而可以引入node.js的一些插件及组件,来根据不同情况做不同处理。

              const path = require("path"); //node.js的路径模块
              let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。
              console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
              
              // 这个导出的对象,就是webpack的配置;
              module.exports = {
                entry: "./src/index.js", //入口文件路径
              
                //出口相关配置
                output: {
                  filename: "index.js", //文件名称
                  path: outputPath, //输出文件的目录
                },
              
                mode: "production", //development开发环境-文件不会压缩,production生产环境-会压缩
              };
              
    • 不同环境的配置

      • 执行不同的脚本命名做不同的打包,分成开发环境和生产环境
        • 方法1 做多个不同的配置执行文件,每一个配置文件对应不同的环境
          1. 在根目录制定做多个不同的配置执行文件,每一个配置文件对应不同的环境

            • webpack.config.development.js

              const path = require("path");
              let outputPath = path.resolve(__dirname, "dist");
              console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
              
              module.exports = {
                entry: "./src/index.js",
              
                output: {
                  filename: "index.[hash].js",
                  path: outputPath,
                },
              
                mode: "development", //development开发环境-文件不会压缩,production生产环境-会压缩
              };
              
            • webpack.config.production.js

              const path = require("path");
              let outputPath = path.resolve(__dirname, "dist");
              console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
              module.exports = {
                entry: "./src/index.js",
              
                output: {
                  filename: "index.[hash].min.js",
                  path: outputPath,
                },
              
                mode: "production", //生产环境-会压缩
              };
              
            • 这个是公司常用的,一个配置对应一个环境,更简洁。逻辑更好理解。

          2. 在package.json中的"scripts"定义的不同执行命令中,使用webpack --config来指定webpack的配置执行文件。

        • 方法2 :相同的配置文件,只不过根据环境变量不同,做一些不同的配置而已。
          • 使用cross-env,拿到cross-env命令执行时配置的NODE_ENV属性的值,根据NODE_ENV属性的值,对同一个配置文件进行处理。
            1. 安装cross-env

              npm i cross-env --save-dev
              
            2. 在package.json中的"scripts"定义的不同执行命令中,使用cross-env NODE_ENV=xxxx来指定NODE_ENV的值。

              {
                "scripts": {
                  "开发": "cross-env NODE_ENV=development webpack",
                  "D": "cross-env NODE_ENV=development webpack",
                  "生产": "cross-env NODE_ENV=production webpack",
                  "P": "cross-env NODE_ENV=production webpack",
                },
              }
              
            3. 在webpack.config.js中通过process.env.NODE_ENV拿到使用cross-env脚本执行时设置的NODE_ENV的值,并根据它对module.exports要返回出去的对象的值进行处理。

              const path = require("path"); //node.js的路径模块
              let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。
              // console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
              
              let NODE_ENV = process.env.NODE_ENV || `production`;
              const theMode = NODE_ENV;
              let outputFilename = `production.js`;
              console.log(`NODE_ENV-->`, NODE_ENV);
              console.log(`process.env.NODE_ENV-->`, process.env.NODE_ENV);
              
              if (NODE_ENV === `development`) {
                outputFilename = `development.js`;
              }
              
              // 这个导出的对象,就是webpack的配置;
              module.exports = {
                entry: "./src/index.js", //入口文件路径
              
                //出口相关配置
                output: {
                  filename: outputFilename, //文件名称
                  path: outputPath, //输出文件的目录
                },
              
                mode: theMode, //development开发环境-文件不会压缩,production生产环境-会压缩
              };
              
            4. 命令终端窗口打开调用package.json中脚本命令

              npm run D
              
  4. 生成html文件

    • 打包压缩出现html文件,将js放到html文件里。
    1. 安装html-webpack-plugin插件,用于在webpack中可以生成一个html文件。

      npm i html-webpack-plugin -–save-dev
      
    2. 在webpack.config.js中插入该插件。

      // 1. 导入插件
      let HtmlWebpackPlugin = require("html-webpack-plugin");
      // const theHtmlWebpackPlugin = new HtmlWebpackPlugin();//默认的配置文件。
      const theHtmlWebpackPlugin = new HtmlWebpackPlugin({
        template: "./public/index.html", //指定自己的html文件
        filename: "index.html", //生成的html的文件名称
        hash: true, //给引入的文添加hash值
        minify: {
          collapseWhitespace: true, //去掉html内容空格
          removeComments: true, //去掉注释
          removeAttributeQuotes: true, //去掉属性的引号
          removeEmptyAttributes: true, //属性值为空的去掉
        },
      });
      const pluginsList = [];
      pluginsList.push(theHtmlWebpackPlugin);
      
      module.exports = {
        plugins: pluginsList, //2. 使用插件,是一个数组。
      }
      
    3. 在package.json中scripts脚本中配置webpack命令

      {
        "scripts": {
          "build": "webpack --config webpack.config.js",//这个是打包命令,在出口文件目录产生文件
          "自定义脚本命令": "webpack",//这个是打包命令,在出口文件目录产生文件
          "fang": "webpack server"//这个是调用本地服务器,不会在出口文件目录产生文件
        },
      }
      
    4. 命令终端窗口打开调用package.json中脚本命令

      npm run build
      
  5. 配置开发服务器

    • 实现热更新,浏览器自动打开,并且可以使用webpack的代理服务器
    1. 安装热更新插件

      npm install webpack-dev-server –save-dev
      
    2. 在webpack.config.js中配置代理服务器插件。

        module.exports = {
          //配置dev-server相关的配置
          devServer: {
            port: "8569", //端口号
            host: "127.0.0.1", //域名
            //compress:true,//是否开启服务器端压缩
            //progress:true,//是否查看编译进度
      
            //打开页面的路径,访问的资源路径
            static: {
              directory: staticDirectory, //要打开页面的路径。
            },
            hot: true, // 是否热更新
            open: true, // 是否自动打开页面
      
            // 配置跨域代理服务器
            proxy: {
              //代理路径1,就尽量使用这一种。表示如果fetch("/proxy/jianshu/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
              "/proxy/jianshu/": {
                target: "https://www.jianshu.com",
                pathRewrite: { "^/proxy/jianshu/": "/" }, //路径重写。替换url,缩短原的旧标识
                changeOrigin: true, //是否伪装访问源
                
              },
              //代理路径2,可以写多个。表示如果fetch("/fang/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
              "/fang/": {
                target: "https://www.jianshu.com",
                pathRewrite: { "^/fang/": "/" }, //路径重写。替换url,缩短原的旧标识
                changeOrigin: true, //是否伪装访问源
              },
              //代理路径3,不建议使用根路径。表示如果fetch("/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
              "/": {
                target: "https://www.jianshu.com",
                pathRewrite: { "^/": "/" }, //路径重写。替换url,缩短原的旧标识
                changeOrigin: true, //是否伪装访问源
              },
            },
          },
        };
      
    3. 在package.json中scripts脚本中配置webpack命令

      {
        "scripts": {
          "自定义脚本命令": "webpack --config webpack.config.production.js",
          "fang": "webpack server",
      
          "build": "webpack",//这个是打包命令,在出口文件目录产生文件
          "serve": "webpack server",//这个是调用本地服务器,不会在出口文件目录产生文件,不会清除上次的出口文件
      
      
          "server": "webpack server"
        },
      }
      
    4. 命令终端窗口打开调用package.json中脚本命令

        npm run serve//开发环境,不会打包出结果,可以热更新
        //npm run build//生产环境,会有打包结果
      
      • 可以实现的效果:
        • 开发环境: 当前服务一直没有结束,当我们代码改变的时候,会自动重新编译,自动刷新浏览器,看最新的效果
        • 生产环境:一直开发,等到功能效果都实现后,我们需要整体打包编译部署到服务器上,【最后把dist文件(打包后的文件),部署到服务器上即可】
      • 原因:
        • 经过之前的配置后,package.json中scripts脚本中webpack server命令是打开一个本地服务器,当我们代码改变的时候,会自动重新编译,自动刷新浏览器,看最新的效果。
        • 经过之前的配置后,package.json中scripts脚本中单纯的webpack命令是把当前的文件打包到配置的出口文件目录上,以便后面部署到服务器上。
  6. 清除旧文件

    1. 安装clean-webpack-plugin插件

      npm i clean-webpack-plugin –save-dev
      
    2. 在webpack.config.js中插入该插件。

      const pluginsList = [];
      
      //"clean-webpack-plugin"用于清除之前打包后文件,再打包新的文件。
      // 1. 导入插件
      let { CleanWebpackPlugin } = require("clean-webpack-plugin");
      const theCleanWebpackPlugin = new CleanWebpackPlugin();
      pluginsList.push(theCleanWebpackPlugin);
      
      module.exports = {
        plugins: pluginsList, //2. 使用插件,是一个数组。
      }
      
    3. 在package.json中scripts脚本中配置webpack命令

      {
        "scripts": {
          "build": "webpack --config webpack.config.production.js",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件
          "D": "cross-env NODE_ENV=development webpack",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件
          "fang": "webpack",//这个是打包命令,在出口文件目录产生文件,配置好了clean-webpack-plugin后会清除上次的出口文件
          "fang": "webpack server"//这个是调用本地服务器,不会在出口文件目录产生文件,不会清除上次的出口文件
        },
      }
      
    4. 命令终端窗口打开调用package.json中脚本命令

      npm run build
      

例子

  • ./package.json

    {
      "name": "demo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "serve": "webpack",
        "自定义脚本命令": "webpack",
    
        "start": "webpack --config webpack.config.development.js",
        "开发环境": "webpack --config webpack.config.development.js",
    
        "build": "webpack --config webpack.config.production.js",
        "生产环境": "webpack --config webpack.config.production.js",
    
        
        "开发": "cross-env NODE_ENV=development webpack",
        "D": "cross-env NODE_ENV=development webpack",
        "生产": "cross-env NODE_ENV=production webpack",
        "P": "cross-env NODE_ENV=production webpack",
    
    
        "fang": "webpack server",
        "server": "webpack server"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "^7.14.5",
        "@babel/plugin-proposal-class-properties": "^7.14.5",
        "@babel/plugin-proposal-decorators": "^7.14.5",
        "@babel/plugin-transform-runtime": "^7.14.5",
        "@babel/preset-env": "^7.14.5",
        "autoprefixer": "^10.2.6",
        "babel-loader": "^8.2.2",
        "clean-webpack-plugin": "^4.0.0-alpha.0",
        "cross-env": "^7.0.3",
        "css-loader": "^5.2.6",
        "file-loader": "^6.2.0",
        "html-webpack-plugin": "^5.3.1",
        "html-withimg-loader": "^0.1.16",
        "less": "^4.1.1",
        "less-loader": "^9.1.0",
        "mini-css-extract-plugin": "^1.6.0",
        "optimize-css-assets-webpack-plugin": "^6.0.0",
        "postcss-loader": "^6.1.0",
        "style-loader": "^2.0.0",
        "terser-webpack-plugin": "^5.1.3",
        "uglifyjs-webpack-plugin": "^2.2.0",
        "url-loader": "^4.1.1",
        "webpack": "^5.38.1",
        "webpack-cli": "^4.7.2",
        "webpack-dev-server": "^4.6.0"
      },
      "dependencies": {
        "@babel/polyfill": "^7.12.1",
        "@babel/runtime": "^7.14.5"
      },
      "browserslist": [
        "> 1%",
        "last 2 versions"
      ]
    }
    
  • ./public/index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>Webpack App</title>
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <script defer="defer" src="production.c70ae7f697e8ce258661.js"></script>
      </head>
      <body>
        <!-- 注释 -->
        <h1 class="className" id="" fang>自己的html文件</h1>
        <div>hot</div>
      </body>
    </html>
    
  • ./src/index.js

    import obj from "./modelA.js";
    console.log(obj.sum(1, 2, 3, 4));
    
    import { average } from "./modelB.js";
    console.log(average(1, 2, 3, 4));
    
    console.log("111111");
    //简书,跨域代理
    fetch("/asimov/subscriptions/recommended_collections")
      .then((response) => {
        return response.json();
      })
      .then((value) => {
        console.log(value);
      });
    
    fetch("/fang/asimov/subscriptions/recommended_collections")
      .then((response) => {
        return response.json();
      })
      .then((value) => {
        console.log("66666fang", value);
      });
    
  • ./src/modelA.js

    const sum=function sum(...params){
      return params.reduce((result,item)=>{
        return result+item;
      })
    }
    export default {
      sum
    }
    
  • ./src/modelB.js

    import obj from "./modelA.js";
    
    export const average= function average(...params){
      let total=obj.sum(...params);
      return total/params.length;
    }
    
  • ./webpack.config.js

    const path = require("path"); //node.js的路径模块
    let outputPath = path.resolve(__dirname, "dist"); //在当前项目的根目录下,创建一个dist文件夹。
    // console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
    
    let NODE_ENV = process.env.NODE_ENV || `production`;
    const theMode = NODE_ENV;
    let outputFilename = `production.js`;
    console.log(`NODE_ENV-->`, NODE_ENV);
    console.log(`process.env.NODE_ENV-->`, process.env.NODE_ENV);
    
    if (NODE_ENV === `development`) {
      outputFilename = `development.js`;
    }
    
    // 1. 导入插件
    let HtmlWebpackPlugin = require("html-webpack-plugin");
    // const theHtmlWebpackPlugin = new HtmlWebpackPlugin();//默认的配置文件。
    const theHtmlWebpackPlugin = new HtmlWebpackPlugin({
      template: "./public/index.html", //指定自己的html文件
      filename: "index.html", //生成的html的文件名称
      hash: true, //给引入的文添加hash值
      minify: {
        collapseWhitespace: true, //去掉html内容空格
        removeComments: true, //去掉注释
        removeAttributeQuotes: true, //去掉属性的引号
        removeEmptyAttributes: true, //属性值为空的去掉
      },
    });
    const pluginsList = [];
    pluginsList.push(theHtmlWebpackPlugin);
    
    //清除之前打包后文件,再打包新的文件。
    let { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const theCleanWebpackPlugin = new CleanWebpackPlugin();
    pluginsList.push(theCleanWebpackPlugin);
    
    let staticDirectory = path.join(__dirname, "dist");
    
    // 这个导出的对象,就是webpack的配置;
    module.exports = {
      entry: "./src/index.js", //入口文件路径
    
      //出口相关配置
      output: {
        filename: outputFilename, //文件名称
        path: outputPath, //输出文件的目录
      },
    
      mode: theMode, //development开发环境-文件不会压缩,production生产环境-会压缩
    
      plugins: pluginsList, //2. 使用插件,是一个数组。
    
      //配置dev-server相关的配置
      devServer: {
        port: "8569", //端口号
        host: "127.0.0.1", //域名
        //compress:true,//是否开启服务器端压缩
        //progress:true,//是否查看编译进度
    
        //打开页面的路径,访问的资源路径
        static: {
          directory: staticDirectory, //要打开页面的路径。
        },
        hot: true, // 是否热更新
        open: true, // 是否自动打开页面
    
        // 配置跨域代理服务器
        proxy: {
          //代理路径1,就尽量使用这一种。表示如果fetch("/proxy/jianshu/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
          "/proxy/jianshu/": {
            target: "https://www.jianshu.com",
            pathRewrite: { "^/proxy/jianshu/": "/" }, //路径重写。替换url,缩短原的旧标识
            changeOrigin: true, //是否伪装访问源
            
          },
          //代理路径2,可以写多个。表示如果fetch("/fang/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
          "/fang/": {
            target: "https://www.jianshu.com",
            pathRewrite: { "^/fang/": "/" }, //路径重写。替换url,缩短原的旧标识
            changeOrigin: true, //是否伪装访问源
          },
          //代理路径3,不建议使用根路径。表示如果fetch("/asimov/subscriptions/recommended_collections")-->fetch("https://www.jianshu.com/asimov/subscriptions/recommended_collections");
          "/": {
            target: "https://www.jianshu.com",
            pathRewrite: { "^/": "/" }, //路径重写。替换url,缩短原的旧标识
            changeOrigin: true, //是否伪装访问源
          },
        },
      },
    };
    
    
  • ./webpack.config.development.js

    const path = require("path");
    let outputPath = path.resolve(__dirname, "dist");
    console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
    
    module.exports = {
      entry: "./src/index.js",
    
      output: {
        filename: "index.[hash].js",
        path: outputPath,
      },
    
      mode: "development", //development开发环境-文件不会压缩,production生产环境-会压缩
    };
    
  • ./webpack.config.production.js

    const path = require("path");
    let outputPath = path.resolve(__dirname, "dist");
    console.log(`打包完成后输出的目录:outputPath-->`, outputPath);
    
    module.exports = {
      entry: "./src/index.js",
    
      output: {
        filename: "index.[hash].min.js",
        path: outputPath,
      },
    
      mode: "production", //生产环境-会压缩
    };
    

进阶参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值