webpack

打包是一个将文件引入并合并到一个单独文件的过程,最终形成一个 “bundle”。 接着在页面上引入该 bundle,整个应用即可一次性加载

一、了解webpack

webpack是一个模块打包器。是在开发阶段使用,开发完了之后上线这些就和webpack一点关系都没有了

浏览器现在还是不支持es6的import这些语法的,所以要把它去交给webpack来处理

安装webpack的依赖:

npm i  // 如果在package.json中写了一些依赖的版本,运行这个命令会自动帮我们添加那些版本上

npm init -y // 初始化一个package.json文件。直接用vscode的终端好像不行,要用git的终端或者cmd

// 安装项目开发的依赖webpack,安装完了之后就会有一个node_modules文件夹了(这个文件夹一般是不动它的),i为install的简写
npm i -D webpack  // npm i -D webpack@3 这个是安装3版本的webpack

npm i -D webpack-cli  // 在webpack 4 之上的版本,需要安装 webpack-cli 不然会报错

二、配置webpack

里面的dev应该指的是development

1、webpack安装插件

  • 安装了插件,如果用的是-S(–save)后缀,则会在package.json的的dependencies(生产阶段依赖)属性中加入插件的信息;如果用的是-D(–save-dev)后缀,则会在package.json的devDependencies属性中加入插件的信息。要使用这个插件需要到webpack.config.js的plugins中去配置
  • html-webpack-plugin: 这个插件默认会自动在打包的路径下去生成一个index.html文件(默认是没有的),这个index.html会自动帮我们引入js。当然调用这个插件的时候依然是可以接收一些参数的。
    • filename: 生成的文件的名字,当然也可以给生成的文件加上一些路径的信息
    • template: 指定模板的文件的路径,这个插件会在模板的基础上加东西(也就是说,模板的东西会保留)。
npm i -D html-webpack-plugin

new HtmlWebpackPlugin({
	filename: '../index.html', // 生成的名字为index.html,且在输出位置的上层路径,比如输出路径为dist/assets,那么输出之后index.html就和assets在同一目录,不过一般是只用index.html的
	template: 'src/index.html' // 模板是src下面的index.html文件
})
  • babel-loader babel-core: 这两个是一起安装的,用来把浏览器不支持的代码,编译成支持的。babel的一些配置(比如用什么插件,用什么预设之类的)可以不到module里面去声明,而写在.babelrc文件中,运行的时候会自动到.babelrc文件中去找
npm i -D babel-loader@7 babel-core
  • postcss-loader css-loader style-loader: postcss-loader用来处理css的兼容性,比如加上前缀这些。css-loader用于可以在文件中使用import的方式引入css。打包之后再用style-loader用来把打包好的css样式插入dom结构里面去
npm i -D postcss-loader
npm i -D css-loader
npm i -D style-loader
  • sass-loader node-sass: 把sass打包成模块
 npm i -D sass-loader node-sass
  • less-loader less: 把less打包成模块,用法和sass一样的
npm i -D less-loader less
  • file-loader: 这个是用来把文件(图片、字体文件)打包成模块的。这个主要是打包css中url里面的那些图片和在js中用模块的方式导入图片,比如background: url(img.jpg), html中的图片就没办法了
$ npm i -D file-loader
  • url-loader: 这个为file-loader的加强版,这个就不把图片打包成路径了,而是把图片进行编码,编码之后就成了base64编码的data:url这种字符串(而网页是可以识别这种字符串的),所以把页面请求回来的时候,这个图片自然就有了(因为图片已经被编码成了字符串嵌套在页面中了),就减少了网络请求。但是,如果图片过大,字符串就很长,这种方法就不好了,就需要用file-loader去打包
$ npm i -D url-loader
  • font-awesome: 这个font-awesome首先是一个字体图标库https://fontawesome.com/,然后要用这个库的字体图标的话,就需要安装这个。安装好了之后,这个就会在node_module里面有个模块
$ npm i -S font-awesome
  • devserver: 这个为webpack里面用的服务器,安装了就可以用了。使用这个是到package.json的scripts里面去添加命令,配置服务器当然还是到webpack.config.js里面去
npm i -D webpack-dev-server

2、webpack中的loader

loader就是webpack用来预处理模块的,在一个模块被引入之前,会预先使用loader来处理模块内容,把浏览器不能直接识别的内容转成浏览器可以直接识别的内容。比如,把es6代码编译成es5语法,那个babel在这里面就是一种loader

每个模块被打包后,都会生成一个模块id,加载到main.js里面去。然后,比如图片被打包了,图片的名字就不是他以前那个名字了,而是一个路径

3、webpack中的devserver

这个为webpack的开发服务器,是webpack专门用来帮我们调试项目的。这样就可以让我们的项目跑在服务器上,然后通过请求来访问我们的项目。ctrl+z退出服务器

运行服务器之前,它会先自动帮我们打包(就像输入打包命令那样),不过它不会把文件直接打包出来,而是放到内存里面,所以我们是不会在打包的输出目录里面找到打包出来的文件的,然后这个服务器运行时先到内存中找文件,没有的话再到我们指定的目录去找文件。服务器的端口号会直接显示在运行的那些代码里面。

这个东西会监视文件的变化,比如我开启了服务器之后,再改变我的文件,那么页面会自动刷新(不用手动刷新)

4、webpack中一些node.js的内置模块

(1)path

首先需要引入模块,然后才可以使用

  • path.resolve(): 表示使用path模块
    • 第一个参数为__dirname代表文件跑起来的根目录
    • 第二个参数为运行到这个根目录下的哪个文件夹
const path = require('path'); // 引入
path.resolve(__dirname, 'dist'); // 使用

5、webpack中一些文件的配置

(1)package.json文件

这个就是整个项目的配置文件了。配置这个文件一定要小心!!!!!!!!它的格式多一个空格都要出错,一定不要乱加注释!!!!!!!!!!!!

注:下面这些很多都是相对自定义命令来说的。

  • scripts: 想要运行的命令就在这个属性后面去声明。声明方式为前面为声明的命令的名字,后面为表示运行声明的命令的时候会运行哪些实际的东西
    • npm run dev:就可以运行新建的那个dev命令(实际上这个为打包命令)。运行了之后,就会调用指定的webpack配置文件,然后在指定的文件夹生成指定的文件,即打包到那个文件去
    • npm run start: 输入这个就可以运行后面的webpack-dev-server服务器了。命令后面那个webpack-dev-server,如果直接这样写的话它是会找webpack.config.js配置文件的,如果我们已经在上面修改了,那么在这里也需要修改
{"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    
    // 下面这条就是新加的命令,表示命令的名字为dev,要运行的为webpack命令
    // webpack命令默认会调用webpack.config.js文件
    // "dev": "webpack", 这个为调用默认文件的配置
    
    // 下面这个为修改webpack默认调用的文件
    // 运行npm run dev之后就会调用webpack.config.dev.js文件
     "dev": "webpack --config=config/webpack.config.dev.js"  //这个config文件 是在config文件夹中的
    //这个命令为devserver服务器的命令
    // "start": "webpack-dev-server"  默认命令,devserver找的配置文件是dev.config.js
    // 由于我们修改了webpack默认的配置文件,所以这里也需要修改
      "start": "webpack-dev-server --config webpack.config.dev.js"
  }}
(2)webpack.config.js

这个就是webpack的配置文件。导出一个对象,这个对象就是webpack的配置了,描述了webpack的一切,会以怎样的方式打包,打包中会干什么,都是这里说明。。由于这个文件是用node.js来跑的,所以这里就需要用node.js的语法,而不是用es6的import

  • mode: 指定webpack使用的模式。
    • development: 开发模式,不会压缩代码
    • production: 生产模式,要压缩代码
  • entry: 这个属性后面跟的是程序的入口位置。值可以字符串、数组、对象,可以为相对路径
    • 一般情况下是main.js文件
  • output: 这个为一个对象。告诉webpack以怎样的方式进行打包,且输出什么东西
    • path属性:表示输出的文件的路径,即资源的打包路径。值为一个绝对路径(可以用path模块来指定),相对路径会报错
    • filename属性:表示输出的所有js文件的名字和路径。值为字符串
    • publicPath属性:这个代码中所有路径的基础路径,在所有资源的输出路径前面加上这个属性的那个字符串。比如,这个属性值为assets/,output的filename为js/main.js,最后代码中引入js的那个路径就为assets/js/main.js。但是,一般来说就用个/就好了
    • 打包之后的文件路径设置:默认的情况下,所有的文件打包之后都会放到path声明的那个路径下面去的,但是这样就很乱,如果我们要到输出目录那里去弄些文件夹的话就需要自己配置。配置的方法是:找到编译文件的那个load或者插件或者output,然后这些东西的name或者filename就是输出后文件的路径(当然还是相对path那个路径的)加上文件的名字,但是这样文件在代码中的引入路径就是我们自己写的这个路径了,不会加上其它东西(所以就会引入资源出错)
  • plugins: 这个属性为一个数组里面的为需要使用的插件。插件需要先用require引入,然后再在数组里面添加插件。添加插件的方法为new这个插件,比如new HtmlWebpackPlugin
  • module: 这个属性为一个对象,是用来配置loader的
    • rules: 这个为一个数组,数组中的每一项为规则对象。规则对象的参数如下:
      • test: 这个为一个条件,用来匹配到要处理的模块(文件)。可以用正则匹配
      • use: 这个为一个规则,表示匹配到了要处理到的文件之后,用什么样的规则(loader)来处理这个文件。这个为一个数组,数组的每一项为loader对象(如果只需要使用这个loader的默认配置的话,就只需要写这个loader的字符串就好了,就不用配置),loadder对象的参数如下
        • loader: 要使用的loader的名字
        • options: 这个用来配置上面的loader。值也为一个配置对象
          • limit: 这个为url-loader的options的配置。值为一个数值,为对图片的最大值进行限制。比如:limit:10000,就为10000b(这个b为bit)之下的图片就用这个配置
          • module: 这个为css-loader的配置。表示为是否开启css模块化,默认为false。
          • name: 这个为file-load的配置。表示生成后的文件的名字
      • exclude: 这个为一个排除数组。即,数组中指定的文件或者文件夹都不运用这个规则
      • include: 这个为一个使用数组。即,只有数组中指定的文件或者文件夹才运用这个规则。和exclude是相反的
  • devServer: 这个属性为一个对象,用来配置devServer(webpack服务器)的
    • open: 值为一个boolean值,即需不需要服务器启动完了之后,自动帮我们打开页面
    • port: 值为一个数字,即需要占用的端口号
    • contentBase: 这个值为一个路径,即devServer在本地找文件的时候,找本地文件的那个路径。默认为dist
// webpack.config.js


const path = require('path');
// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin'); 

module.exports = { // 导出一个对象
    mode: 'development',
    entry: './src/app.js',
    output: {
    // 这个运行了npm run dev之后就会把所有的东西打包到dist/文件夹下
    // 如果没有dist会自动创建
    // 多次运行会覆盖以前的main.js文件
        path: path.resolve(__dirname, 'dist/'),
        filename: 'assets/js/main.js', // 这个为所有js的名字和路径
        publicPath: '/' // 如果,指定代码中所有资源的基础路径为assets/,给所有资源代码中的路径前面加上这个字符串,比如上面那个代码中的路径就变为了assets/js/main.js
    },
    // 下面这个为使用插件
    plugins: [
         new HtmlWebpackPlugin({
        	filename: 'index2.html', // 一般html的输出路径是不变的
        	template: 'src/index.html' // 也可以写成path.resolve(__dirname, 'src/index.html')
        })
    ],
    module: {
    	rules: [{
    	    test: /\.js/, // 即匹配所有的js文件
    	    use: [{
    	    	loader: 'babel-loader', // 使用babel-loader
    	    	options: {
    	    		presets: ['react'], // 用react预设来处理react语法内容
    	    		plugins: ['transform-object-rest-spread']
    	    	}
    	    }],
    	    exclude: [path.resolve(__dirname,'node_modules')] // 排除node_modeles文件夹中的js文件(排除了之后性能要好些),因为它里面的不需要用这些
    	},
    	{
    	    test: /\.css$/,
    	    use: ['style-loader',
    	    {
                loader: 'css-loader',
                module: false // 关闭css模块化
            }],
            exclude: [
                path.resolve(__dirname,'src/common')
            ],
            include: [
                path.resolve(__dirname,'src/common')
            ]
    	},
    	{
            test: /\.s(a|c)ss$/,
            use: ['style-loader','css-loader','sass-loader',]
        },
    	{
    	    test: /\.(jpg|ttf|eot|woff|woff2|svg)$/, // ttf|eot|woff|woff2都为字体文件
    	    use: [{
    	       loader: 'file-loader',
    	       // name: 'what' 这个就为匹配到的所有文件都输出这个名字,下面那个就是动态匹配
    	       // [name]为文件的名字,[hash:8]为去文件的8位hash编码长度,.[ext]为匹配到的文件的后缀名
    	        // name: '[name]_[hash:8].[ext]' 
    	        name: 'assets/font/[name]_[hash:8].[ext]'  // 这个就是把文件打包后,在打包目录再新建一个font文件夹,把文件放到font文件夹下面
    	    }]
    	},
    	{
    	    test: /\.(ttf|jpg|jpeg|png|gif)$/,
    	    use: [{
    	    	loader: 'url-loader',
    	    	options: {
    	    		limit: 10000, // 小于10000b的图片就用这个配置,被编码成字符串
    	    		name: 'assets/img/[name]_[hash:8].[ext]'
    	    	}
    	    }]
    	}]
    },
    devServer: {
        open: true,
    	port: 9000
    }
};
(3)main.js文件

这个文件一般来说就是程序的入口文件,由于webpack中所有的资源都被认为是个模块,所以这个js文件中也可以引入其他类型的文件,比如.css文件

// main.js

import React from 'react' 
import ReactDom from 'react-dom'

import './common/style/main.css'; // 只是引入,不使用的话,就可以不声明前面那个变量
import Hammer from './common/img/Hammer.gif'; // 引入图片,因为图片也是模块(实际上是使用file-loader进行打包或者用url-loader把图片进行编码), 这个Hammer变量(为一个路径或者一个编码),就代表这个图片了

import 'font-awesome/css/font-awesome.css' // 这个为引入font-awesome的字体图标,直接用font-awesome开头路径就好了,因为它是个模块

const img = `<img src=${Hammer}>`;

6、babel

babel是一个js编译器,比如可以把es6代码编译成es5代码。babel官网http://babeljs.io/

1、使用babel
  • babel使用
npm init // 首先还是要初始化一个package.json文件出来
npm -i -D babel-cli // -D命令是--save-dev的简写
npm -i -g babel-cli // 这个命令是把babel-cli安装到全局
  • package.json
// package.json
{"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    // src/app.js为需要用babel编译的那个文件路径
    // -o代表后面是输出路径,out/js为编译后的js路径
    "babelgo": "babel src/app.js -o out/a.js" 
    
  }}
  • .babelrc: 这个文件是babel的插件,babel运行package.json的时候,就会在这里找需要哪些插件
    • 预设(preset):就是把所有相关的插件弄到一起就是一个预设。因为如果一个一个的引入插件太麻烦了,所以就直接引入预设
      • babel-preset-env: 这个预设代表兼容所有的es已经在规范里面的新特性预设,包括es2015,es2016等
      • babel-preset-es2015: 这个预设代表是用es2015特性
      • babel-plugins-transform-object-rest-spread: 这个插件用来支持还不在规范里面的es语法
// .babelrc
{
    "plugins": ["transform-object-rest-spread"], // 这个为需要使用的插件
    "preset": ["env", "es2015"] // 这个为需要使用的预设
}

三、webpack问题解决

  • (1)清楚产生的log文件:npm cache clean
  • (1)关闭8080端口:输入netstat -ano|findstr 8080查看占用8080端口的进程,
// 查看占用8080端口的进程,就会出现一个进程号
netstat -ano|findstr  8080  
// 运行windows自带taskkill命令,将上面显示的进程号,结束掉, 4708为进程号
taskkill  /pid  4708  /f 

四、完整webpack配置

文件结构如下:

- config
    - webpack.common.js
    - webpack.dev.js
    - webpack.prod.js
- src
    - css
        - a.css
    - img
        - go.png
    - index.js
- package.json

插件安装:

// 基础插件
npm init -y // 初始化一个package.json文件。直接用vscode的终端好像不行,要用git的终端或者cmd
// 安装项目开发的依赖webpack,安装完了之后就会有一个node_modules文件夹了(这个文件夹一般是不动它的),i为install的简写
npm i -D webpack  // npm i -D webpack@3 这个是安装3版本的webpack
npm i -D webpack-cli  // 在webpack 4 之上的版本,需要安装 webpack-cli 不然会报错

// loader
npm i -D babel-loader@7 babel-core // 解析es6
npm i -D postcss-loader css-loader style-loader // 打包css
npm i -D file-loader url-loader // 打包图片

// 其余插件
npm i -D webpack-dev-server // 用于开启服务器
npm i -D html-webpack-plugin // 用于打包进html
npm i -D webpack-merge // 用于代码拆分
npm i -D clean-webpack-plugin // 用于每次打包的时候清除上一次 output文件夹
npm i -D mini-css-extract-plugin // 抽离压缩css用的,替换style-loader
npm i -D terser-webpack-plugin // 抽离压缩css用的,替换style-loader
npm i -D optimize-css-assets-webpack-plugin // 抽离压缩css用的,替换style-loader

package.json:

{
  "name": "lyTrip-copy",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --config config/webpack.dev.js", // 开发环境,使用 webpack-dev-server 来启动服务器
    "build": "webpack --config config/webpack.prod.js" // 生产环境,使用 webpack 来进行打包
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^4.3.0",
    "file-loader": "^6.1.0",
    "html-webpack-plugin": "^4.4.1",
    "mini-css-extract-plugin": "^0.11.2",
    "optimize-css-assets-webpack-plugin": "^5.0.4",
    "postcss-loader": "^4.0.2",
    "style-loader": "^1.2.1",
    "terser-webpack-plugin": "^4.2.1",
    "url-loader": "^4.1.0",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0",
    "webpack-merge": "^5.1.4"
  }
}

webpack.common.js: 里面只配置 基本的 入口、babel-loader 和 htmlWebpackPlugin

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: {
    index: path.resolve(__dirname, "../src/index.js"),
    // uploadError: path.join(srcPath, 'uploadError.js'),
    // advertisement: path.join(srcPath, 'advertisement.js')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: ["babel-loader"],
        include: path.resolve(__dirname, "../src"),
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "../index.html"),
      filename: "index.html",
    }),
  ],
};

webpack.dev.js:开发环境的配置,只配置 devServer 、css的loader 和 图片的loader

const path = require("path");
const webpackCommonConf = require("./webpack.common.js");
const { merge } = require("webpack-merge");
module.exports = merge(webpackCommonConf, {
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: ["style-loader", "css-loader", "postcss-loader"], // 加了 postcss。loader 的执行顺序是:从后往
      },
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        use: "file-loader", // 直接引入图片 url
      },
    ],
  },
  // plugins: [new webpack.DefinePlugin({ENV: JSON.stringify('development')})],
  devServer: {
    port: 8080,
    progress: true, // 显示打包的进度条
    contentBase: path.resolve(__dirname, "../dist"), // 根目录
    open: true, // 自动打开浏览器
    compress: true, // 启动 gzip 压缩
    proxy: {},
  },
});

webpack.prod.js:生产环境配置,配置 css拆分、图片url-loader 和 js的代码拆分

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpackCommonConf = require("./webpack.common.js");
const { merge } = require("webpack-merge");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(webpackCommonConf, {
  mode: "production",
  output: {
    filename: "bundle.[contentHash:8].js", // 打包代码时,加上 hash 戳
    path: path.resolve(__dirname, "../dist"),
    // publicPath: distPath  // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
    publicPath: "./static/",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        // loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss。loader 的执行顺序是:从后往
        loader: [
          MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader
          "css-loader",
          "postcss-loader",
        ],
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 1, //如果大于或等于2048Byte,则按照相应的文件名和路径打包图片;如果小于2048Byte,则将图片转成base64格式的字符串。
              name: "[name]_[hash:8].[ext]",
              outputPath: "image",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
    // new webpack.DefinePlugin({ENV: JSON.stringify('production')}),
    new MiniCssExtractPlugin({ filename: "css/main.[contentHash:8].css" }), // 抽离 css 文件
  ],
  optimization: {
    minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], // 压缩 css

    // splitChunks: { // 分割代码块
    //     chunks: 'all', // initial 入口 chunk,对于异步导入的文件不处理。async 异步 chunk,只对异步导入的文件处理。all 全部 chunk
    //     cacheGroups: { // 缓存分组
    //         vendor: { // 第三方模块
    //             name: 'vendor', // chunk 名称
    //             priority: 1, // 权限更高,优先抽离,重要!!!
    //             test: /node_modules/,
    //             minSize: 0,  // 大小限制
    //             minChunks: 1  // 最少复用过几次
    //         },
    //         common: { // 公共的模块
    //             name: 'common', // chunk 名称
    //             priority: 0, // 优先级
    //             minSize: 0,  // 公共模块的大小限制
    //             minChunks: 2  // 公共模块最少复用过几次
    //         }
    //     }
    // }
  },
});

文件代码如下:

// index.html
<!DOCTYPE html> <html class="no-js">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="./src/css/a.css">
    </head>
    <body>
        <div class='go'>this is a demo<div class='go2'></div></div>
        <script src="./src/index.js" async defer></script>
    </body>
</html>

// index.js
import './css/a.css';
import img from './img/go.png';
window.onload = function() {
    console.log('aaaaa');
    console.log(css);
    console.log(img);
    const go = document.querySelector('.go2');
    go.appendChild(`<img src="${img}" alt=""/>`);
}

// a.css
.go {background: url(../img/go.png) no-repeat;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值