Webpack入门

相关

安装

1.初始化: npm init -y(默认初始化,不加-y一路回车)

2.安装一下webpack:全局:npm install -g webpack
当前项目: npm install --save-dev webpack

webpack 4以上还需要安装webpack-cli:npm install --save-dev webpack webpack-cli

3.创建配置文件:webpack.config.js

//六大体系
module.exports={
 //一:打包生成环境
 //1.开发development  2.生产模式(代码压缩混淆)production
 mode:“production”,

 //二:入口(js来源)
 entry:'目标js',   //多个时可以用数组/对象(不能合并jq等插件)

 //三:出口(生成的配置)
 outpu:{
     filename: '生成的文件名.js',
     path: '/生成的路径'
 },

 //四:loader  
 //(webpack默认只能打包js文件,打包其他入css图片等需要在这里定义(先npm导入对应包))
 //如npm install --save-dev css-loader
 module:{
     //匹配文件规则
     rules:[
         {
               //正则
             test:/\.css$/,
             //对应包:顺序:从后到前
             use:['css-loader']   
         }
     ]
 },

 //五:plugin:插件(一些插件:如打包html的html-webpack-plugin)
 //(需要先在前面导入对应插件 )

 plugins:[
     // 插件
 ],

 //六:开发环境配置:实现自动化
 devServer:{
 }


}

创建打包脚本命令

  • 全局安装webpack下可以直接执行命令:webpack
  • 局部安装情况下可以使用:npx webpack

1.在package.json中的scripts节点中定义脚本命令
2.npm run 对应定义的脚本命令

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack -p",//上线模式打包
    "dev": "webpack"//开发模式打包
  },
  • 当名字不为webpack.config.js时需要自动指定:

npm webpack(可以改为脚本命令) --config 对应文件名

  • 当脚本命令只有webpack时-----输入脚本命令时带参数:

npm dev --(双杆后面带参数) -p

创建服务(devServer)

  • 热部署

1.npm install --save-dev webpack-dev-server
2.npx webpack-dev-server
3.通过生成的localhost进行访问

devServer:{
    //要运行的项目的根目录(根路径)
    constentBase:resolve(_dirname,'对应目录'),
    //启动gzip压缩
    compress:true,
    //运行的端口
    port:8080,
    //自动打开浏览器
    open:true,
    //服务代理----> 解决跨域
    proxy:{
        //匹配对应的路径进行代理
        //例如匹配到http://localhost/api将代理为https://xxx
        '/api':{
            target:'https://xxx'//发送请求是,请求路径重写,将'/api'重写为''
            pathRewrite:{
                '^/api':''
            }
        }
    }
}

五个核心

//webpack.config.js

module.exports = {
    //1.入口
    entry: "./runoob1.js",
    //2.出口
    output: {
        path: __dirname,
        filename: "bundle.js"
    },
    //3.其他资源
    module: {
        rules: [
            { test: /\.css$/, loader: "style-loader!css-loader" }
        ]
    },
    //4.插件
    plugins:[
        new webpack.BannerPlugin('菜鸟教程 webpack 实例')
    ],
    //5.打包模式
    mode: 'production',
};

1.Entry:入口文件

entry:字符串|数组|对象
  • 默认只能打包js
module.exports = {
    //指定输入文件
    //1.字符串:单一js文件
    entry:'./src/js/index.js',
    //2.数组:多个js文件合成一个
    entry:['./src/js/index.js','./src/js/index2.js'],
    //3.对象:为每个js文件指定打包名
    entry: {
        //为每一个js文件命名
        first: __dirname + '/src/first.js',
        second: __dirname + '/src/second.js',
    },

}
  • 对象语法
  • dependOn: 当前入口所依赖的入口。它们必须在该入口被加载前被加载
  • filename: 指定要输出的文件名称
  • import: 启动时需加载的模块
  • library: 指定 library 选项,为当前 entry 构建一个 library。
  • runtime: 运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。在 webpack 5.43.0 之后可将其设为 false 以避免一个新的运行时 chunk。
  • publicPath: 当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址。请查看 output.publicPath

runtimedependOn 不应在同一个入口上同时使用

//b2在a2之前被加载
module.exports = {
  entry: {
    a2: 'dependingfile.js',
    b2: {
      dependOn: 'a2',
      import: './src/app.js',
    },
  },
};

2.Output:输出文件

  • filename:输出的文件名
  • path:指定输出的路径
  • 输出单个
module.exports = {
  output: {
    //单一文件,文件输出到 dist 目录中
    filename: 'bundle.js',
    //单一文件指定输出路径文件名
    filename:'js/index.js',
  },
};
  • 输出多个

[name]:会自动指定entry指定的js文件名

[hash]:随机生成hash值

//输出:./dist/app.js, ./dist/search.js
module.exports = {
  entry: {
    app: './src/app.js',
    search: './src/search.js',
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist',
  },
};

3.Loader:除js外的资源

官方提供的一些loader

Webpack本身只能识别js

非js文件处理需要用到Loader

  1. 需要先安装loader 模块

打包css需要用到两个

  • css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串

  • style-loader:创建style标签,将js中的样式资源插入,添加到页面中生效

npm install --save-dev css-loader style-loader
  1. 配置对应的rules

两种模式

配置指定(推荐)
  • loader 从右到左(或从下到上)

例如:打包css需要先用css-loader打包css文件后,用style-loader在页面创建style标签,并将这些文件内容插入

module.exports = {
  module: {
    rules: [
      { 
          test: /\.css$/,
          use: [
              'style-loader',
              'css-loader'/* {
                  loader: 'css-loader',
                  options: {
                    modules: true
                  }
              },*/
          ]
      },
    ],
  },
};
import
  • ! 将资源中的 loader 分开,每部分相当于当前目录解析
import Styles from '!style-loader!css-loader?modules!./styles.css';
  • !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
import Styles from '!!style-loader!css-loader?modules!./styles.css';
  • -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
import Styles from '-!style-loader!css-loader?modules!./styles.css';

4.Plugins:插件

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

官方提供的一些Plugin

  1. 下载插件
npm install html-webpack-plugin -d
  1. 配置
2.//引入插件
const HtmlWebPackPlugin = require('html-webpack-plugin');
3.配置
//为一个对象类
//1.创建一个空的Html文件,*自动引入*打包好输出的所有资源(js/css)

//一个html指定一个模板
//多个html需要指定多个
const HtmlWebPack = new HtmlWebPackPlugin({
	//定义一个html模板,
	template: './src/index.html',
    //指定输出文件,默认为index.html,不指定时会被覆盖
    filename:'index.html',
    //压缩
    minify:{
         //移除空格
         collapseWhitespace : true,
         //移除注释
         removeComments: true,
         removeAttributeQuotes: true, //清除多余引号
   },

   //指定插入模板中的js文件数组队列(entry中定义的名字),
   //不匹配将默认全部插入
   chunks:  [ 'entryName' ],

   //生成html文件的favicon的路径

   //是否为静态资源添加hash
    hash: true
});



4.在插件模块导入
module.exports = {
    plugins: [
        HtmlWebPack
    ]   
}

5.Mode:打包模式

  • 生产:production
  • 开发:development

实操

打包js

module.exports = {
    //指定输入文件(3选一)
    //1.字符串:单一js文件
    entry:'./src/js/index.js',
    //2.数组:多个js文件合成一个
    entry:['./src/js/index.js','./src/js/index2.js'],
    //3.对象:为每个js文件指定打包名
    entry: {
        //为每一个js文件命名
        'first': __dirname + '/src/first.js',
        'second': __dirname + '/src/second.js',
    },



    //输出文件
    output:{
        //单一文件指定输出路径文件名
        //可以指定路径
        filename:'js/index.js',
        //多个js文件需要一一指定文件名
        //[name]会自动指定entry指定的js文件名,,以及 HtmlWebpackPlugin 插件 中的 chunk 对应
        filename:  'js/[name].js',
        //输出文件的根目录
        path:path.resolve(__dirname,'dist')
    }
}
    

打包样式

less(其他)需要先转化为css文件然后进行css文件的处理方式

  • less-loader和less(配置时候less不需要写入,只需要写less-loader)

  • sass-loader依赖于node-sass

module.exports = {
    module:{
        rules:[
           {
                test:/\.s(a|c)ss$/,
                use:['style-loader','css-loader','sass-loader']
            },
        ]
    }
}

分离出css样式为单独文件

mini-css-extract-plugin插件
MiniCssExtractPlugin.loader:替换style-loader实现打包后是以link导入的

module:{
    rules:[
        {
            test:/\.css$/,
            use:[
                //替换style-loader ,提取js中的css成单独文件
                //其他样式也将style-loader替换成这个
                MiniCssExtractPligin.loader,
                'css-loader'
            ],
            //exclude :/指定不匹配的内容/
        }
    ]
},
plugins:[
    new   MiniCssExtractPlugin({
        //指定输出文件
        //这里还可以用[name]等
        //这里需要注意不能对文件名使用[hash],不然会导致css的模块热替换失效
        filename:'./css/index.css'
    })               
]

压缩css

//利用插件:optimize-css-assets-webpack-plugin


const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
//直接new
plugins:[
    new OptimizeCssAssetsWebpackPlugin()
]

打包html

官方配置文档

1.下载插件:npm install html-webpack-plugin -D

  • 简单用法
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
<!--自动生成一个原始的html文件,自定义需要提供模板-->
<!--打包完后将会生成以下形式,自动将打包生成的js引入-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title> 
        <%=htmlWebpackPlugin.options.title%> 
    </ title> 
    <script defer src="index_bundle.js"></script>
  </head>
  <body>
  </body>
</html>

  • 复杂用法
//2.引入插件
const HtmlWebPackPlugin = require('html-webpack-plugin');
//为一个对象类
//1.创建一个空的Html文件,*自动引入*打包好输出的所有资源(js/css)

//一个html指定一个模板---------多个html需要指定多个
const HtmlWebPack = new HtmlWebPackPlugin({
	//定义一个html模板,(默认为空html模板)
	template: './src/index.html'//指定输出文件,默认为index.html,不指定时会被覆盖
    filename:'index.html',
    //压缩
    minify:{
         //移除空格
         collapseWhitespace : true,
         //移除注释
         removeComments: true,
         removeAttributeQuotes: true, //清除多余引号
    },
    //指定插入模板中的js文件数组队列,不匹配将默认全部插入,entry中对象模式的key值
                                         
    chunks:  [ 'chunksName' ],
    //生成html文件的favicon的路径
    //是否为所包含的脚本和css资源添加hash(有效解决缓存问题)
    //为所有js和css等静态资源路径上添加?hash值
    hash: true
});

//4.在插件模块导入
module.exports = {
	plugins: [
		HtmlWebPack
	]
}
  • htmlWebpackPlugin:相当于这个插件的实例
    • options:通过这个获取一些配置信息

打包图片

  • webpack5移除了4中的url-loaderfile-loader

webpack4

url-loader的功能类似于file-loader,但可以在文件小于指定大小时转化为base64编码,可减少Http请求次数,提高访问效率

  • 例如小于8kb会被转码,不指定限制的话将全部被转base64
  • 超出指定大小将使用file-loader打包
  • 拥有file-loader的全部配置
  • 依赖于file-loader,需要一起下载
npm install -D file-loader url-loader
//分两种:css中和html中----------------
module:{
    rules:[
        //需要解决css打包
        { 
            test:/\.css$/,
            use:[ 'style-loader',  'css-loader']},

        //-------css文件中的url引用图片资源
        {  

            test:/\.( jpg | png | gif )$/,

            //单个loader用法
            //url-loader进行打包url-loader是依赖于file-loader(需要两个一起下载)
            loader:'url-loader',

            //配置
            options: {
                //小于指定大小会被base64编码,例如小于8kb会被转码//不指定限制的话将全部被转base64
                //优:减少请求(减轻服务器压力)
                //劣:图片体积会变大,请求速度变慢
                limit: 8 * 1024,

                //问题:url-loader默认为es6模块化,html-loader引入是commonjs ,在html-loader解析后出现路径为[object Module]
                //解决:关闭url-loader的es6模块化 ,使用commonjs
                esModule:false  

                //打包后名字为随机生成的Hash值
                //指定hash长度 :[hash:10]:取前十位     [ext]:取原来的扩张名

                name: '[hash:10].[ext]'//指定输出文件夹
                outputPath:'img'                        
            }
        },
        //------------------------html文件中的src引用图片资源
        {
            test:/\.html$/,
            //处理html文件的img图片(负责引入img,从而能被url-loadeer进行处理)
            loader: 'html-loader'
        }
    ]


}

webpack5

  • 资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
    • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
    • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
    • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
    • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现

在5中使用url-loader可能会导致图片打包冲突

  • 在css背景中引入图片会导致又打包了一张图片在根目录(原因是因为asset module也打包了一次)

  • 需要添加type: 'javascript/auto'来自动解决

{
    test: /\.(png|jpg|jpeg|avg|gif)/,
    loader: 'url-loader',
    options: {
       //。。。
    },
    type: 'javascript/auto'
}
module.exports = {
    //输出文件
    output: {
        //webpack5为资源指定名字
        assetModuleFilename: 'images/[name][hash:5][ext][query]'
    },
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg|avg|gif)/,
                //其他内容看wepack5官网
                type:'asset/resource'
            }
        ]
    }

}

同时打包css和html图片

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                //配置下MiniCssExtractPlugin.loader,避免出现路劲错误
                use: [
                    //对象模式
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            //在这里设置publicPath的路径就是background-img的路径 
                            //指定公用路径,在当前文件调用文件调用加入前缀
                            //默认情况下是在webpackOptions.output中使用publicPath
                            publicPath: '../'
                        }
                    }, 

                    //普通模式
                    'css-loader'
                ]
            },
            //配置图片----------------------------
            {
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
                    //不指定限制的话将全部被转base64
                    limit: 8 * 1024,
                    //指定文件夹
                    outputPath: 'img',
                    esModule: false,
                    //指出公用的路径,在调用时以这个为根路径调用,需要与输出路径配合
                    // publicPath:'assets/img',  
                }
            },
            //打包html中的-------------------------
            //处理html文件的img图片(负责引入img,从而被url-loader进行处理)
            {
                test: /\.html$/,
                loader: 'html-loader',
            }
        ]
    },
}

打包其他资源

//------打包除html,css,js,图片等其他资源,例如阿里的图标文字类
module:{
    rules:[
        //排除法
        {
            exclude:/\.(css | js | html | less | png | jpg | gif)$/,
            loader: 'file-loader',
            options:{
                name:'[hash:10].[ext]'//指定输出文件夹
                outputPath:'media'          
            }

        },
    ]

}


自动化

//------使用devServer实现自动化(热编译,自动编译,自动打开浏览器,自动刷新)
//-----------需要webpack-dev-server包支持
//-------------局部安装时启动devServer:npx webpack-dev-server


const Webpack = require("webpack")

module.exports={
    devServer:{

        //静态资源的根目录
        //webpack5改为了static
        contentBase : path.resolve(_dirname,'dist'),

        //启动gzip压缩
        compress : true,

        //指定端口号(注意端口,避免出错)
        port : 8888,

        //自动打开浏览器
        open:true,
        
        //开启模块热替换
        hot:true

    },
    plugins: [
        new OptimizeCssAssetsWebpackPlugin(),
        // 启动热更新功能插件
        //只修改更新的内容,无需刷新页面
        new Webpack.HotModuleReplacementPlugin(),
        // 帮助减少不需要的信息展示
        new Webpack.NoEmitOnErrorsPlugin()
    ],
}

配置SourceMap(源代码映射)

实现代码的打包成果(打包后分为原代码(便于定位错误),编过的等,详情看devtool配置

devtool:"对用的模式",
///
----none//默认,适用于生产
eval//生成后的代码
cheap-eval-source-map//转换过的代码
---cheap-module-eval-source-map//用于开发环境

分开环境配置

  • --config 指定运行的文件

创建webpack.dev.jswebpack.prod.js抽离根据环境配置,然后修改npm脚本命令指定打包的时候运行对应的配置文件

"scripts":{
    "dev":"webpack-dev-server --config ./webpack.dev.js",
     "build":"webpack --config ./webpack.prod.js"
}

抽离公共配置代码

文档

  • 安装webpack-merge抽离重复代码

    //引入抽离的公共代码
    const baseConfig = require("./xxxx");
    //引入工具
    const merge = require("webpack-merge");
    //单独配置信息
    const prodConfig = {
        //....
        plugins: [
            //这里和公共配置文件同时使用了HtmlWebpackPlugin,直接用merge合并打包时候会出错,合并的时候需要用提供的mergeWithCustomize自定义字段
            new HtmlWebpackPlugin({
               //...
                minify:{
                    collapseWhitespace:true,//清除空格
                    removeComments:true,//移除注释
                    removeAttributeQuotes:true,//清除多余引号
                },
                //为所有js和css等静态资源路径上添加?hash值
                //有效解决缓存问题
                hash:true
            }),
    }
    
    //导出合并后的
    module.exports = merge(baseConfig,prodConfig);
    
  • 保持插件的唯一性,采用自定义字段(例如默认配置文件和生产配置文件同时用到了HtmlWebpackPlugin,这样会报错)

  • 解决HtmlWebpackPlugin(插件)重复出现的错误

    /**
     * mergeWithCustomize:实现自定义字段
     * ---------------
     * unique是一种用于在配置中强制唯一性的策略。
     * - 确保插件唯一性
     * - 并且是最后一个插件实例
     * 参数:1.查找的config字段,2.要去重的config下的字段,3.输出返回一个插件
     */
    //下面实现用当前配置文件的HtmlWebpackPlugin
    const webpackConfig = mergeWithCustomize({
        customizeArray: unique(
          "plugins",
          ["HtmlWebpackPlugin"],
          (plugin) => plugin.constructor && plugin.constructor.name
        ),
      })(
        BaseConfig,
        ProdConfig
      );
    
    module.exports = webpackConfig
    

解析ES6语法

部分低版本浏览器不支持es6语法

  • 需要用babel将es6转化为es5
  1. 安装
npm install --save-dev babel-loader @babel/core
  1. 配置规则
{
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
  1. 实际做转化的是@babel/preset-env,安装
npm install --save-dev @babel/preset-env
  1. 根目录创建babel.config.json配置启动一些预设
{
  "presets": ["@babel/preset-env"]
}

打包iconfont

  • 创建src/assets/iconfont,将阿里矢量图标下载的内容放入(下载对应图标,下载提供的demo有对应的使用说明)
module.exports = {
    module: {
        rules: [
            {
                test: /\.(woff2|woff|ttf)$/,
                loader: "url-loader",
                options: {
                    name: "[name][hash:5].[ext]",
                    limit: 1024,
                    outputPath: "icon",
                    esModule: false,
                    // publicPath: "../"
                },
                type: "javascript/auto"
            }
        ]
    }
}

sass和less的全局问题

使用sass-resources-loader可以使得在所用sass(less)共享全局变量、mixin和函数等。不再需要一个个去加载他们。

npm i -D sass-resources-loader
module.exports = {
    module: {
        {
                test: /\.s(a|c)ss$/,
                use: [
                   {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            publicPath: "../"
                        }
                    },
                    "css-loader",
                    "postcss-loader",
                    
                    "sass-loader",
                    {
                        //先用sass-resources-loader处理
                        loader:"sass-resources-loader",
                        options:{
                            //指定全局样式文件路径(数组)
                            resources:[path.resolve(__dirname,"src/assets/style/global.scss")]
                        }
                    }
                ]
            },
    }   
}

vue-cli中则需要用到预处理器 Loader

// vue.config.js
module.exports = {
    css: {
        loaderOptions: {
            // 给 sass-loader 传递选项
            sass: {
                // @/ 是 src/ 的别名
                // 所以这里假设你有 `src/variables.sass` 这个文件
                // 注意:在 sass-loader v8 中,这个选项名是 "prependData"
                additionalData: `@import "~@/variables.sass"`
            },

        }
    }

拷贝文件插件

copy-webpack-plugin

const copyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    plugins:[
        new CopyPlugin([
            {
                from:'哪里(可*多个)',
                to:'拷贝到哪里'
            }
        ])
    ]
}
new CopyPlugin({
    patterns:[{
        from:'哪里(可*多个)',
        to:'拷贝到哪里'
    }]
})

拷贝static下的文件

  • 这里下载低版本(新版本会报错)
npm i -D copy-webpack-plugin@9.*
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                { 
                    from: path.resolve(__dirname,"src/static"), 
                    to:  path.resolve(__dirname,"dist/static"),
                },
            ],
        }),
    ]
}

打包分析

  • webpack-bundle-analyzer

设置别名,指定引入的包是指定包下的

Vue打包下生成三个文件:

//运行时版本

  • rentime only 的文件 vue.common.js

//编译时版本

  • compiler only 的文件compiler.js

//平时时候用的版本

  • runtime+compiler的文件vue.js
resolve:{
    alias:{
        //在导入vue的时候指定加载包
        'vue':'vue/dist/vue.js'
    }
}

错误集合

  • 模块热替换报Maximum call stack size exceeded

因为package.json中配置的脚本写了webpack-dev-server --hot,--hot与webpack.config.js中new webpack.HotModuleReplacementPlugin()两者冲突,删除一个

  • css模块热替换失效

由于设置了[hash]

new   MiniCssExtractPlugin({
    //指定输出文件
    //这里还可以用[name]等
    //这里需要注意不能对文件名使用[hash],不然会导致css的模块热替换失效
    filename:'./css/index.css'
    //下面这条导致css热替换失效
    // filename:'./css/[name][hash:5].css'
}) 
  • 出现:ERROR in Conflict: Multiple assets emit different content to the same filename index.html
  • HtmlWebpackPlugin是否设置了filename字段(默认设置为index.html)(设置多次HtmlWebpackPlugin的时候需要单独指名)
  • 使用webpack-merge合并配置文件的时候同时设置了HtmlWebpackPlugin,导致认为要多文件输出,单需要唯一时候,需要用mergeWithCustomize自定义字段
  • sass(less)全局变量问题
  • 需要用 sass-resources-loader处理
  • vue-cli需要配置css预处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值