Webpack从0小计

Webpack体系学习

占位符:[name]_[hash]

lifecycle_4a919f7471e246973e7380cf0871a739.png

一、为什么使用 webpack?
1. 在面向对象开发中存在的问题

1.不易维护,各各文件间,牵一发而动全身,易出bug

—src 例子:

  • —index.html
  • —content.js
  • —header.js
  • —footer.js
  • —index.js
  1. index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>为什么使用 webpack?</title>
    </head>
    <body>
    <div id="app"></div>
    <script src="content.js"></script>
    <script src="footer.js"></script>
    <script src="header.js"></script>
    <script src="./index.js"></script>
    </body>
    </html>
    
  2. index.js

    // 面向对象  这种写法,对代码的维护性,拓展性不利,
    // 1. 从当前目录下并不能知道其他文件的变量名,变量冲突。。
    // 2. 在index.html文件中,引入的 js文件过多会导致,加载变慢!
    // 由此引出  webpack 的解决方案:
    const app = document.getElementById('app');
    new Footer();
    new Header();
    new Footer();
    
  3. footer.js

    function Footer() {
      const footer = document.createElement('div');
      footer.innerHTML = 'Footer';
      app.appendChild(footer)
    }
    
  4. content.js

    function Content() {
      const content = document.createElement('div');
      content.innerHTML = 'Content';
      app.appendChild(content);
    }
    
  5. header.js

    function Header() {
      const header = document.createElement('dic');
      header.innerHTML = 'Header';
      app.appendChild(header);
    }
    
  6. 结果:

    image-20211028145907259

2. webpack解决方案-使用原因

优势:

  1. 使用一个 js文件,减少了 http的请求次数:只用一次即可
  2. 方便维护,模块与模块之间的冲突少
  3. 能够使用 CommonJS、ES6 模板
  4. 加之 webpack的其他优势:压缩,非 JS文件的使用…等等
  1. 只保留一个 index.js引入

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>为什么使用 webpack?</title>
    </head>
    <body>
    <div id="app"></div>
    <script src="./index.js"></script>
    </body>
    </html>
    
  2. 在 index.js文件下 import导入依赖 js文件

    import Header from './header.js'  // 这是 export 默认的方式!!!
    import Content from './content.js'
    import Footer from './footer.js'
    
    const app = document.getElementById('app');
    new Footer();
    new Header();
    new Content();
    
  3. 在其他 js文件中 export 导出

    // content.js
    function Content() {
      const app = document.getElementById('app');
      const content = document.createElement('div');
      content.innerHTML = 'Content';
      app.appendChild(content);
    }
    
    export default Content;
    
    //footer.jsfunction Footer() {  const app = document.getElementById('app');  const footer = document.createElement('div');  footer.innerHTML = 'Footer';  app.appendChild(footer)}export default Footer;
    
    // headerfunction Header() {  const app = document.getElementById('app');  const header = document.createElement('dic');  header.innerHTML = 'Header';  app.appendChild(header);}export default Header;
    
  4. 配置 webpack.config.js

    const path = require('path')module.exports = {  // 模式:mode?这个有什么作用?  mode:'development',  // 入口:__dirname :webpack.config.js的目录,src:src文件的index.js 文件开始打包  entry: path.join(__dirname,'src','index.js'),  // 出口:path,输出到那个目录下,filename:输出文件的名字!  output:{    path:path.join(__dirname,'dist'),    filename:'bundle.js'  },}
    
  5. 配置 packages.json 文件

    {  "name": "myWebpack",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {      // 能够使用 npm run webpack的关键    "build": "webpack"  },  "keywords": [],  "author": "",  "license": "ISC",  "devDependencies": {    "webpack": "^5.60.0",    "webpack-cli": "^4.9.1"  }}
    
  6. npm run build 打包

    dist文件,在 index.html中引入 dist的文件

    <!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>为什么使用 webpack?</title></head><body><div id="app"></div><script src="../dist/bundle.js"></script></body></html>
    
  7. 结果:

    image-20211028161251041

二、webpack的运行原理|流程
深入浅出:https://webpack.wuhaolin.cn/3%E5%AE%9E%E6%88%98/3-9%E4%B8%BA%E5%8D%95%E9%A1%B5%E5%BA%94%E7%94%A8%E7%94%9F%E6%88%90HTML.html手撸实现webpack:https://segmentfault.com/a/1190000021494964

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler),当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph), 其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

**webpack 就像一条生产线,**要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。

webpack 通过 Tapable 来组织这条复杂的生产线。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好

1.初始化参数

从配置文件和 shell 语句中读取于合并参数,得出最终的参数

2.开始编译

用上一步得到的参数初始化 Compiler对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。

3.确定入口

根据配置中的 entry 找出所有的入口文件

4.编译模块

从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理

5.完成模块编译

在经过第4步使用的 Loader 翻译完所有模块后,得到每个模块被翻译后的最终内容以及他们之间的依赖关系。

6.输出资源

根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会

7.输出完成

在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果
三、Webpack的核心概念
1.入口-entry

**入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。**进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的

  1. 单个入口语法(用法)

    webpack.config.js

    module.exports = {    entry:'./path/to/my/entry/file.js'}
    
  2. 多个入口时

    module.exports = {    entry:{        main:'./src/index.js',        sub:'./src/index.js'    }}
    
  3. 分离 应用程序(app) 和 第三方库(vendor) 入口

    module.exports = {     entry: {         app: './src/app.js',         vendors: './src/vendors.js'  }}
    
  4. 多页面应用程序

    module.exports = {  entry: {    pageOne: './src/pageOne/index.js',    pageTwo: './src/pageTwo/index.js',    pageThree: './src/pageThree/index.js'  }};
    

    **这是什么? ** 告诉 webpack 需要 3 个独立分离的依赖图,三个入口文件

    **为什么?**在多页应用中,(译注:每当页面跳转时)服务器将为你获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。然而,这给了我们特殊的机会去做很多事:

    • 使用 CommonsChunkPlugin 为每个页面间的应用程序共享代码创建 bundle。由于入口起点增多,多页应用能够复用入口起点之间的大量代码/模块,从而可以极大地从这些技术中受益,这样可以加快页面加载的速度,提高用户的体验。

    根据经验:每个 HTML 文档只使用一个入口起点

2.出口-output

output 属性告诉 webpack 在哪里输出它所创建的 bundles以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

  1. 基本用法

    output 属性有最低要求:值须设为 一个对象,包含下面两点

    • filename 用于输出文件的文件名。
    • 目标输出目录 path 的绝对路径。
    module.export = {  output: {    filename: 'bundle.js',    path: '/home/proj/public/assets'  }};
    

    此配置将一个单独的 bundle.js 文件输出到 /home/proj/public/assets 目录中。

  2. 多个入口起点情况

    {  entry: {    app: './src/app.js',    search: './src/search.js'  },  output: {    // `[name].js`  占位符    filename: '[name].js',           path: __dirname + '/dist'    }}// 写入到硬盘:./dist/app.js, ./dist/search.js
    

    如下图:占位符使用以及,publicPath:‘http…’,地址前+前缀

    image-20211028161959050

  3. 高级进阶

    以下是使用 CDN 和资源 hash 的复杂示例:

    config.js

    output: {  path: "/home/proj/cdn/assets/[hash]",  publicPath: "http://cdn.example.com/assets/[hash]/"}
    

    在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空,并且在入口起点文件运行时动态设置。如果你在编译时不知道 publicPath,你可以先忽略它,并且在入口起点设置 __webpack_public_path__

    __webpack_public_path__ = myRuntimePublicPath
    
    // 剩余的应用程序入口
    
3. loader

webpack 是默认知道 .js 文件的,对应其他的如 .css .jpg .png是不知道,这就需要使用–loader 来处理

loader 用于模块的源代码进行转换。

  • loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript

  • 或将内联图像转换为 data URL

  • loader 甚至允许你直接在 JavaScript 模块中 import CSS文件

1. webpack 加载图片-file-loader
  1. 引入图片,绑定挂载在页面上

    // 默认是,无法识别这个文件的
    import lifecycle from './lifecycle.png';
    
    var img = new Image();
    img.src = lifecycle;
    
    var app = document.getElementById('app');
    app.appendChild(img)
    
  2. 局部安装 file-loader

    npm install file-loader --save-dev

  3. 配置 webpack.config.js 的 module

    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const { CleanWebpackPlugin } = require('clean-webpack-plugin')
    
    module.exports = {
      // 模式:mode?这个有什么作用?
      mode:'development',
      // 入口:__dirname :webpack.config.js的目录,src:src文件的index.js 文件开始打包
      entry: path.join(__dirname,'src','index.js'),
      // 出口:path,输出到那个目录下,filename:输出文件的名字!
      output:{
        path:path.join(__dirname,'dist'),
        filename:'bundle.js'
      },
      plugins:[
          new HtmlWebpackPlugin({
            // 指定生成文件的路径
            template:path.join(__dirname,'src','index.html'),
            // 指定生成文件的名字
            filename: 'index.html'
          }),
          // 清除上一打包 dist
          new CleanWebpackPlugin()
      ],
      module:{
        rules:[
          {
            test:/.png|jpg|gif$/,
            // use: 'file-loader'
            // 保持图片名打包前后一致
            use:{
              loader:'file-loader',
              options:{
                // 占位符: placeholder [name]  & [hash]
                name:`[name]_[hash].[ext]`
              }
            }
          }
        ]
      }
    }
    
  4. 重新打包 npm run build

  5. 结果:

    image-20211028170658652

    image-20211028170620261

2. webpack 加载图片-url-loader

修改配置文件即可:将 file-loader —》改成 url-loader

就没有 图片的文件了,图片都转成 url 形式

// CommonJS语法

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  // 模式:mode?这个有什么作用?
  mode:'development',
  // 入口:__dirname :webpack.config.js的目录,src:src文件的index.js 文件开始打包
  entry: path.join(__dirname,'src','index.js'),
  // 出口:path,输出到那个目录下,filename:输出文件的名字!
  output:{
    path:path.join(__dirname,'dist'),
    filename:'bundle.js'
  },
  plugins:[
      new HtmlWebpackPlugin({
        // 指定生成文件的路径
        template:path.join(__dirname,'src','index.html'),
        // 指定生成文件的名字
        filename: 'index.html'
      }),
      // 清除上一打包 dist
      new CleanWebpackPlugin()
  ],
  module:{
    rules:[
      {
        test:/.png$/,
        // use: 'file-loader'
        // 保持图片名打包前后一致
        use:{
          loader:'url-loader',
          options:{
            // 占位符: placeholder [name]  & [hash]
            name:`[name]_[hash].[ext]`,
            // 指定 图片的存放位置
            outputPath:'images/'
          }
        }
      }
    ]
  }
}

image-20211028200247860

image-20211028200213504

3.webpack 加载图片-file+url-loader并用
  • 使用 url-loader 打包图片:

    好处: dist 少了 .jpg 图片文件 ,就减少了一次图片 HTTP请求

    **弊端:**页面加载,js加载完毕图片 -> bundle.js (base64) 图片过大,会导致bundle.js 过大,最终导致页面加载完毕时间很长,出现空白页面。

合理的处理方式:

  • 图片只有 1、2kb 时,使用url-loader(bundle.js-base64)
  • 图片很大时,就使用 file-loader,生成单独的 .jpg图片文件去发送额外的 HTTP请求,JS首次加载时间就很短,页面可以很快出来
  module:{
    rules:[
      {
        test:/.png$/,
        // use: 'file-loader'
        // 保持图片名打包前后一致
        use:{
          loader:'url-loader',
          options:{
            // 占位符: placeholder [name]  & [hash]
            name:`[name]_[hash].[ext]`,
            // 指定 图片的存放位置
            outputPath:'images/',
            // 单位:2 kb = 2048,50kb = 51200
            limit: 52000
          }
        }
      }
    ]
  }

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CuQh2CAQ-1635504669703)(C:/Users/13059/AppData/Roaming/Typora/typora-user-images/image-20211028201906467.png)]

image-20211028202019368

我嘞个去!牛奶项目根本就没有对图片区分打包

4.style-loader & css-loader打包样式 css
  • **style-loader:**将生成的css代码插入到header中
  • **css-loader:**根据.css文件的引用关系生成一段css代码
  • loader数组从下向上执行的!!!
  1. 安装 对应的 loader

    // 安装加载 css文件的
    npm install --save-dev css-loader
    // 安装加载 typescript文件的(将 ts转换成JS)
    npm install --save-dev ts-loader
    // 本次使用
    npm install style-loader css-loader -save-dev
    
  2. 修改配置文件

      module:{
        rules:[
          {
            test:/.png$/,
            // use: 'file-loader'
            // 保持图片名打包前后一致
            use:{
              loader:'url-loader',
              options:{
                // 占位符: placeholder [name]  & [hash]
                name:`[name]_[hash].[ext]`,
                // 指定 图片的存放位置
                outputPath:'images/',
                // 单位:2 kb = 2048
                limit: 52000
              }
            }
          },
          // style|css-loader  
          {
            test: /.css$/,
            // loader 数组从下向上执行的  
            use: [
                // 将生成的css代码插入到header中
                'style-loader',
                // css-loader:根据.css文件的引用关系生成一段css代码
                'css-loader'
            ]
          }
        ]
      }
    
5.sass-loader&postcss-loader打包样式 scss
  • sass-loader: 引用scss的依赖关系
  • postcss-loader: 转换代码兼容浏览器设置
    1. 因为 scss 低版本的浏览器不一定支持,使用 postcss-loader解决这个问题.
    2. postcss-loader 需要 插件:autoprefixer
    3. 安装命令:npm install autoprefixer --save-dev
  1. 导入需要的 loader

    npm install sass sass-loader --save-dev
    npm install postcss-loader --save-dev
    
  2. 配置文件 webpack.config.js

      module:{
        rules:[
          {
            test:/.png$/,
            // use: 'file-loader'
            // 保持图片名打包前后一致
            use:{
              loader:'url-loader',
              options:{
                // 占位符: placeholder [name]  & [hash]
                name:`[name]_[hash].[ext]`,
                // 指定 图片的存放位置
                outputPath:'images/',
                // 单位:2 kb = 2048
                limit: 52000
              }
            }
          },
          {
            test: /.scss$/,
            use: [
                'style-loader',
                'css-loader',
                'postcss-loader',
                'sass-loader'
            ]
          }
        ]
      }
    
  3. 配置 postcss-loader

    postcss.config.js

    module.exports = {
      plugins:[
          require('autoprefixer')
      ]
    }
    
  4. 配置 package.json

    image-20211028224127850

6.CSS-loader 启动CSS模块化
  1. 存在的问题:

    • 在未使用 css模块化时,因为是全局引入的样式,会改变我并不想作用的元素

    image-20211029085203081

    image-20211029085259427

  2. 解决方式:利用 css-loader 实现 css 模块化

    梳理流程: 1.npm工具安装 loader,2.配置 webpackconfig.js 文件,3.将样式引入置于变量,使用模块化的类名引入方式

    1. 修改 webpack.config.js 的配置

        module:{
          rules:[
            {
              test:/.png$/,
              // use: 'file-loader'
              // 保持图片名打包前后一致
              use:{
                loader:'url-loader',
                options:{
                  // 占位符: placeholder [name]  & [hash]
                  name:`[name]_[hash].[ext]`,
                  // 指定 图片的存放位置
                  outputPath:'images/',
                  // 单位:2 kb = 2048
                  limit: 52000
                }
              }
            },
            {
              test: /.scss$/,
              use: [
                  'style-loader',
                  // 'css-loader',
                   {
                     loader:'css-loader',
                     options:{
                       modules:true
                     }
                   },
                  'postcss-loader',
                  'sass-loader'
              ]
            }
          ]
        }
      
    2. 引入 css时,特性化说明 ${styleCss.lifecycle}

      // 默认是,无法识别这个文件的
      import lifecycle from './lifecycle.png';
      
      // 这个是全局的 scss引用
      import styleCss from './index.scss';
      import createLife from "./createLife.js";
      
      // 执行这个函数
      createLife();
      
      var img = new Image();
      img.src = lifecycle;
      // 只给后面一个绑定样式-模块化样式
      img.className += `${styleCss.lifecycle}`;
      
      var app = document.getElementById('app');
      app.appendChild(img)
      
    3. 结果展示和梳理

      image-20211029090446433

7.file-loader 打包字体图标
5.使用 Loader

有三种使用 loader 方式:

  1. 配置-Configuration

    module.rules 允许你在 webpack 配置中指定多个 loader。 这是展示 loader 的一种简明方式,并且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:

      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              { loader: 'style-loader' },
              {
                loader: 'css-loader',
                options: {
                  modules: true
                }
              }
            ]
          }
        ]
      }
    
  2. 内联

    可以在 import 语句或任何等效于 “import” 的方式中指定 loader。使用 ! 将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。

    import Styles from 'style-loader!css-loader?modules!./styles.css';
    

    通过前置所有规则及使用 !,可以对应覆盖到配置中的任意 loader。

    选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}

  3. CLI

    你也可以通过 CLI 使用 loader:

    这会对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loadercss-loader

    webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
    
6. loader 特性
  • loader 支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照相反的顺序执行。loader链式的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack所预期的 Javascript。
  • loader 可以是同步的,也可以是异步的。
  • loader 运行在 Node.js 中,执行能够执行的任何可能的操作。
  • loader 接收查询参数。用于对 loader 传递配置。
  • loader 也能够使用 options 对象进行配置。
  • 除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段。
  • 插件(plugin)可以为 loader 带来更多特性。
  • loader 能够产生额外的任意文件。

loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。 用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和其他更多

7.解析 loader

loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常将模块路径认为是 npm install, node_modules)解析。

loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。通常使用 npm 进行管理,但是也可以将自定义 loader 作为应用程序中的文件。按照约定,loader 通常被命名为 xxx-loader(例如 json-loader)。有关详细信息,请查看 如何编写 loader?

4.插件-plugin

插件目的

  • 在于解决 loader 无法实现的其他事

插件是 webpack 的支柱功能。webpack 自身也是构建于插件,你在 webpack 配置中用到的相同的插件系统之上!

ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
    apply(compiler) {
        compiler.hooks.run.tap(pluginName, compilation => {
            console.log("webpack 构建过程开始!");
        });
    }
}

compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。

1. plugin使用(dist目录下自动创建 index.html)
  1. npm install html-webpack-plugin --save-dev

    npm 工具安装 对应插件

  2. 配置 webpack.config.js

    const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
    const webpack = require('webpack'); //访问内置的插件
    const path = require('path');
    
    const config = {
      entry: './path/to/my/entry/file.js',
      output: {
        filename: 'my-first-webpack.bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            use: 'babel-loader'
          }
        ]
      },
      plugins: [
        new webpack.optimize.UglifyJsPlugin(),
        new HtmlWebpackPlugin({
        // 指定生成文件的路径
        template:path.join(__dirname,'src','index.html'),
          // 指定生成文件的名字  
          filename: 'index.html'
        })
      ]
    };
    
    module.exports = config;
    
  3. 最后再运行 npm run build 脚本的打包

    image-20211028192410116

    对比:

    image-20211028192533943

2. Node API

即便使用 Node API,用户也应该在配置中传入 plugins 属性。compiler.apply 并不是推荐的使用方式。

some-node-script.js

  const webpack = require('webpack'); //访问 webpack 运行时(runtime)
  const configuration = require('./webpack.config.js');

  let compiler = webpack(configuration);
  compiler.apply(new webpack.ProgressPlugin());

  compiler.run(function(err, stats) {
    // ...
  });

以上看到的示例和 webpack 自身运行时(runtime) 极其类似。wepback 源码中隐藏有大量使用示例,可以用在配置和脚本。有时间再去看了!!!

5.模式-mode

提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。

1.用法

只在配置中提供 mode 选项:

module.exports = {`` ``mode: ``'production'``};

或者从 CLI 参数中传递:

webpack --mode=production
2.支持字符串值:

1.development

会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。

// webpack.development.config.js
module.exports = {
+ mode: 'development'
- plugins: [
-  new webpack.NamedModulesPlugin(),
-  new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}

2.production

会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.

// webpack.production.config.js
module.exports = {
+ mode: 'production',
- plugins: [
-  new UglifyJsPlugin(/* ... */),
-  new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
-  new webpack.optimize.ModuleConcatenationPlugin(),
-  new webpack.NoEmitOnErrorsPlugin()
- ]
}

production模式下会启用UglifyJsPlugin插件(移除未使用的内容和文件压缩),分别用production和development打包,编译的区别:

1.development打包后,一些没有依赖的方法 变量 文件会保留,production则会移除。

2.production打包后,代码会进行压缩,比development的文件小。

6.配置-configuration
1. devtool: ‘eval-cheap-module-source-map’

用于线上代码出现错误情况,方便定位错误位置:cheap-module-source-map 这个配置错误更加全面

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  // devtool
  devtool:'',    
  // 模式:mode?这个有什么作用?
  mode:'development',
  // 入口:__dirname :webpack.config.js的目录,src:src文件的index.js 文件开始打包
  entry: path.join(__dirname,'src','index.js'),
  // 出口:path,输出到那个目录下,filename:输出文件的名字!
  output:{
    path:path.join(__dirname,'dist'),
    filename:'index.js'
  },
  plugins:[
      new HtmlWebpackPlugin({
        // 指定生成文件的路径
        template:path.join(__dirname,'src','index.html'),
        // 指定生成文件的名字
        filename: 'index.html'
      }),
      // 清除上一打包 dist
      new CleanWebpackPlugin()
  ],

}
2.WebpackDevServer
  1. 安装 WebpackDevServer

    npm install webpack-dev-server --save-dev

  2. 配置 webpack.config.js

      devServer:{
        port: 8000,
        static: path.join(__dirname,'dist')
      }
    
  3. 配置 package.json

     "scripts": {
        "build": "webpack", // 打包快捷命令
        "dev": "webpack-dev-server" // 运行快捷命令
      },
    
  4. 启动:npm run dev

    这样就可以自动更新了,原理:相对于将 dist放在内存中,每改变一次,更新一次 内存的 dist

    image-20211029104004616

3.WebpackDevServer请求转发

用于,开发环境的接口地址的使用,这样配置之后,使用相对路径,上线就不用改了

  1. index.js :入口文件

    import axios from 'axios';
    
    //axios.get('http:study.jspluplus.com/Yixiantong/getHomeDatas').then(({data}) =>{
    //    console.log(data)
    //})
    axios.get('/Yixiantong/getHomeDatas').then(({data}) =>{
        console.log(data)
    })
    
  2. 配置 devServer

    一旦碰上这个路径:’/Yixiantong’就转发到 target:‘http:study.jsplusplus.com’,

      devServer:{
        port: 8000,
        // static: path.join(__dirname,'dist'),
        contentBase:'./dist',
        proxy:{     
          '/Yixiantong':{
            target:'http:study.jsplusplus.com',
            changeOrigin:true
          }
        }
      }
    
  3. 剔除路径某字符

    image-20211029110600855

7.模块热替换-hot module replacement

提高开发调试的效率,其中css的css-loader封装了,可以直接使用 HMR热部署

而原始的 JS并没有,因此需要开发自己写,当然在Vue 中有这一部分功能

image-20211029111854922

image-20211029112352077

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值