zoukankan      html  css  js  c++  java
  • 如何用webpack搭建vue项目?本文案例详解

    前言:都2020年了,感觉是时候该学一波webpack了,趁着最近有时间,就学了一下,等把官网上的webpack结构和模块大概看了一遍之后,就感觉可以开始搭个项目实战一下了,从0开始,一步步记录下来

    使用版本: webpack4.x

    1.包含插件和loader

    * html:    
      html-webpack-plugin clean-webpack-plugin
    
    * css:    
      style-loader css-loader sass-loader node-sass postcss-loader autoprefixer
    
    * js:      
      babel-loader @babel/preset-env @babel/core @babel/polyfill core-js@2 @babel/plugin-transform-runtime
      @babel/runtime  @babel/runtime-corejs2
    
    * vue:     
      vue-loader vue-template-compiler vue-style-loader vue vue-router axios vuex
    
    * webpack: 
    
      file-loader url-loader webpack-dev-server webpack-merge copy-webpack-plugin happypack HardSourceWebpackPlugin 
      webpack-bundle-analyzer optimize-css-assets-webpack-plugin  portfinder  FriendlyErrorsPlugin
    另外要注意 :光理论是不够的。在此赠送2020最新企业级 Vue3.0/Js/ES6/TS/React/node等实战视频教程,想学的可进裙 519293536 免费获取,小白勿进哦

    2.webpack功能

    -- 生成hmtl模板
    -- 删除上一次的dist文件
    -- 自动添加浏览器前缀
    -- 使用sass预编译器
    -- 转换ES6,7,8,9语法为ES5
    -- 大于10k文件打包到dist,小于10k转换为base64
    -- 兼容vue-- 拷贝静态文件
    -- 热更新
    -- 区分当前环境
    -- 多线程打包
    -- 缓存未改变模块
    -- g-zip压缩
    -- 获取本机ip
    -- 打包大小分析
    -- 压缩css
    -- 检查端口是否存在复制代码

    3.实现步骤

       1. 初体验

    1. 新建一个文件 取名为webpack-vue
    
    2. cd webpack-vue  npm init -y  npm i -D webpack webpack-cli
    
    3. 新建 src/main.js ,里面随便写点 console.log('hello,webpack')
    
    4. 修改 package.json - >scripts ,添加 "build":"webpack src/main.js"
    
    5. 然后 npm run build 如果多了一个dist文件,那么初次打包就成功了复制代码

       2. 配置

    1.  新建一个 build 文件夹,新建一个 webpack.config.js
    2.  写入以下内容  
    const path=require('path')
    
    module.exports = {
        mode:'development',
        entry:path.resolve(__dirname,'../src/main.js'),  //入口文件
        output:{
            filename:'[name].[hash:8].js',   //打包后的名字  生成8位数的hash
            path.resolve(__dirname,'../dist')   //打包的路径
         }
     }
    
     然后修改 package.json ->scripts,修改为: "build":"webpack --config build/webpack.config.js"  
    
     然后npm run build复制代码

     3. 我们生成了main.js之后,不可能每次都手动在index.html里面引入,所以我们需要这个插件来帮我们自动引入

    先安装插件: 

    npm i -D html-webpack-plugin复制代码

    根目录新建一个 public/index.html

    修改webpack.config.js:

    const path = require('path');
      const HtmlWebpackPlugin = require('html-webpack-plugin')   //这里引入插件
      module.exports = {
          mode:'development', // 开发模式
          entry: path.resolve(__dirname,'../src/main.js'),    // 入口文件
          output: {
            filename: '[name].[hash].js',      // 打包后的文件名称
            path: path.resolve(__dirname,'../dist')  // 打包后的目录
          },
          //插件注入
          plugins:[
            new HtmlWebpackPlugin({
              template:path.resolve(__dirname,'../public/index.html')
            })
          ]
      }复制代码

    然后npm run build 就会发现dist里面多了index.html,并且已经自动帮我们引入了main.js

    4. 由于hash每次生成的不同,导致每次打包都会将新的main.js打包到dist文件夹,所以我们需要一个插件来打包前删除dist文件

    先安装插件: 

    npm i -D clean-webpack-plugin复制代码
    webpack.config.js
    
    const {CleanWebpackPlugin} = require('clean-webpack-plugin')   //引入
    
     plugins:[
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,'../public/index.html')
        }),
        new CleanWebpackPlugin()
     ]
    复制代码

    5.我们一般把不需要打包的静态文件放在public里面,这个地方不会被打包到dist,所以我们需要使用插件来把这些文件复制过去

    先安装插件:

    npm i -D  copy-webpack-plugin复制代码
    webpack.config.js
    
    const CopyWebpackPlugin = require('copy-webpack-plugin')      // 复制文件
    
    plugins: [
       new CopyWebpackPlugin({
          patterns: [
            {
              from: path.resolve(__dirname, '../public'),
              to: path.resolve(__dirname, '../dist')
            }
          ]
        })
    ]复制代码

    6. 为了让webpack识别css,我们需要安装loader,并将解析后的css插入到index.html里面的style

    先安装:

    npm i -D style-loader css-loader复制代码
     webpack.config.js
    
    module.exports = {
        module:{
            rules:[{
              test:/.css$/,
              use:['style-loader','css-loader'] // 从右向左解析原则
            }]
        }
    }复制代码

    7.我们这里可以使用预编译器更好的处理css,我这里使用的是sass

    先安装:

    npm install -D sass-loader node-sass

     webpack.config.js
    
    module:{
        rules: [{
            test: /.scss$/,
            use: ['style-loader', 'css-loader', 'sass-loader'] // 从右向左解析原则
        }]
    }复制代码

    8. 自动添加浏览器前缀

    先安装:

    npm i -D postcss-loader autoprefixer

    webpakc.config.js
    
      module: {
          rules: [
            {
              test: /.scss$/,
              use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] // 从右向左解析原则   sass-loader必须写后面
          }]
      }
    
     在根目录新建  .browserslistrc
    
     这个里面配置兼容的浏览器
    
     这里贴下我的默认配置,可以根据实际情况自己去配置
    
     > 1%
    last 2 versions
    not ie <= 8
    
    再新建一个postcss.config.js
    
    module.exports = {
      plugins: [require('autoprefixer')]  // 引用该插件即可了
    }
    
    这样打包后就自动帮你添加浏览器前缀了复制代码

    9.之前的style-loader只是把css打包到index.html里面的style-loader里面,如果css特别多这种办法肯定不行,所以我们需要单独抽离提取css

    先安装:

    npm i -D mini-css-extract-plugin

     webpack.config.js
    
    const MiniCssExtractPlugin = require("mini-css-extract-plugin")   //提取css
    
    module: {
        rules: [{
              test: /.scss$/,
              use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] // 从右向左解析原则
        }]
    }
    
    plugins: [
        new MiniCssExtractPlugin({
            filename: "css/[name].[hash:8].css",
            chunkFilename: "[id].css",
        })
    ]
    
    这样打包后就将css打包到css文件下里面了复制代码

    10. 我们为了减少图片字体等打包的大小,我们可以使用url-loader将少于指定大小的文件转换为base64,使用file-loader将大于指定大小的文件 移动到指定的位置

    先安装:

    npm i -D file-loader url-loader

     webpack.config.js
    
     module:{
        rules:[
          {
            test:/.(jpe?g|png|gif|svg)(?.*)?$/            //图片
            use:[{
              loader:'url-loader',
              options:{
                limit:10240,
                fallback:{
                  loader:'file-loader',
                  options:{
                    name:'img/[name].[hash:8].[ext]',
                    publicPath: '../'       //为了防止图片路径错误
                  }
                }
              }
            }]
          },{
            test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,
            use: [{
              loader: 'url-loader',
              options: {
                limit: 10240,
                fallback: {
                  loader: 'file-loader',
                  options: {
                    name: 'media/[name].[hash:8].[ext]',
                    publicPath: '../'
                  }
                }
              }
            }]
          },{
            test:/.(woff2?|eot|ttf|otf)(?.*)$/,
            loader:'url-loader',
            options:{
              limit:10240,
              fallback:{
               loader:'file-loader,
               options:{
                 name:'fonts/[name].[hash:8].[ext]',
                 publicPath: '../'
               }
            }
            }
          }
        ]
      }
    
    webpack只会转换和移动项目中使用了的图片
    
    打包后发现图片字体等也打包进去了复制代码

    11.为了兼容浏览器,我们需要将ES6,7,8,9转换为Es5

    先安装:

    npm install -D babel-loader @babel/preset-env @babel/core复制代码
     webpack.config.js
    
    module: {
        rules: [{
            test: /.js$/,
            use: ['babel-loader']
        }]
    }
    
    根目录新建  .babelrc
    
    {
      "presets": [
        "@babel/preset-env"
      ]
    }
    
    
    一些新的api如Promise,set,Maps等还不支持转换,所以我们需要另一个插件babel/polyfill,但是这个插件会将所有的poly都打包到
    mian.js里面,所以我们需要另一个插件 core-js@2  来按需加载
    
    `npm i -s @babel/polyfill core-js@2`
    
    修改.babelrc
    
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": false,
            "useBuiltIns": "usage",
            "corejs": 2,
            "targets": {
              "browsers": [
                "last 2 versions",
                "ie >= 10"
              ]
            }
          }
        ]
      ]
    }
    
    还有一个问题,会影响全局依赖,所以我们需要另一个插件来解决这个问题
    
     npm i @babel/plugin-transform-runtime -D
     npm i --save @babel/runtime
     npm i --save @babel/runtime-corejs2
    
    修改.babelrc
    
    {
      "presets": [
        "@babel/preset-env"
      ],
      "plugins": [
        [
          "@babel/plugin-transform-runtime",
          {
            "helpers": true,
            "regenerator": true,
            "useESModules": false,
            "corejs": 2
          }
        ]
      ]
    }
    
    这样就完美解决ES6新api的兼容问题了复制代码

    12.兼容vue

    先安装:

     npm i -D vue-loader vue-template-compiler vue-style-loader
    
     npm i -S vue 复制代码
    webpack.config.js
    
    const vueLoaderPlugin=require('vue-loader/lib/plugin') 
    function resolve(dir) {
      return path.join(__dirname, '..', dir)
    }
    
     module:{
        rules:[{
            test:/.vue$/,
            use:[vue-loader]
        }]
     },
    resolve:{
        alias:{
            'vue$':'vue/dist/vue.runtime.esm.js',
            '@':path.resolve(__dirname,'../src')
        },
        extensions: ['.js', '.vue', '.json'],
    },
    plugins:[
       new vueLoaderPlugin()
    ]
    
    这样配置完成之后就可以webpack就识别了vue文件复制代码

    13.热更新

      先安装:

     npm i -D webpack-dev-server复制代码
     wepack.config.js
    
    const webpack = require('webpack')
    
    devServer: {
        compress: true,
        port: 8989,
        hot: true,
        inline: true,
        hotOnly: true,  //当编译失败时,不刷新页面
        overlay: true,  //用来在编译出错的时候,在浏览器页面上显示错误
        publicPath: '/',  //一定要加
        open: true,
        watchOptions: {
          // 不监听的文件或文件夹,支持正则匹配
          ignored: /node_modules/,
          // 监听到变化后等1s再去执行动作
          aggregateTimeout: 1000,
          // 默认每秒询问1000次
          poll: 1000
        }
      },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
    ]
    
    在package.json里面配置: "dev":"webpack-dev-server --config build/webpack.config.js"
    
    在main.js里面
    
    import Vue from "vue"
    import App from "./App"
    
    new Vue({
        render:h=>h(App)
    }).$mount('#app')
    
    src文件夹内新建一个APP.vue,内容自定义
    
    然后npm run dev  页面就运行起来了复制代码

    14.区分开发环境和生产环境

    build文件夹内新建 webpack.dev.js  webpack.prod.js复制代码
    开发环境:
    
    1.不需要压缩代码
    2.热更新
    3.完整的soureMap
    ...
    
    生产环境:
    
    1.压缩代码
    2.提取css文件
    3.去除soureMap (根据个人需要)
    ...复制代码

    我们这里需要安装 webpack-merge 来合并配置项

    先安装:

    npm i -D webpack-merge   复制代码
    webpack.dev.js
    
    const webpackConfig = require('./webpack.config')
    const merge = require('webpack-merge')
    const webpack = require('webpack')
    
    module.exports = merge(webpackConfig, {
      mode: 'development',
      devtool: 'cheap-module-eval-source-map',
      devServer: {
        compress: true,
        port: 8989,
        hot: true,
        inline: true,
        hotOnly: true,  //当编译失败时,不刷新页面
        overlay: true,  //用来在编译出错的时候,在浏览器页面上显示错误
        publicPath: '/',  //一定要加
        open: true,
        watchOptions: {
          // 不监听的文件或文件夹,支持正则匹配
          ignored: /node_modules/,
          // 监听到变化后等1s再去执行动作
          aggregateTimeout: 1000,
          // 默认每秒询问1000次
          poll: 1000
        }
      },
      module: {
        rules: [
          {
            test: /.js$/,
            use: ['babel-loader']
          },
          {
            test: /.css$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader'],
          },
          {
            test: /.scss$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
            exclude: /node_modules/
          }
        ]
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
      ]
    })复制代码
     webpack.prod.js
    
    const webpackConfig = require('./webpack.config')
    const merge = require('webpack-merge')
    const path = require('path')
    const { CleanWebpackPlugin } = require('clean-webpack-plugin')     //清除dist
    const MiniCssExtractPlugin = require("mini-css-extract-plugin")   //提取css
    
    function resolve(dir) {
      return path.join(__dirname, '..', dir)
    }
    
    module.exports = merge(webpackConfig, {
      mode: "production",
      devtool: 'none',
      optimization: {
        splitChunks: {
          chunks: 'all',
          cacheGroups: {
            vendors: {
              name: 'vendors',
              test: /[\/]node_modules[\/]/,
              priority: -10,
              chunks: 'initial'
            },
            common: {
              name: 'chunk-common',
              minChunks: 2,
              priority: -20,
              chunks: 'initial',
              reuseExistingChunk: true
            }
          }
        }
      },
      module: {
        rules: [
          {
            test: /.js$/,
            use: ['babel-loader']
            exclude: /node_modules/,
            include: [resolve('src'), resolve('node_modules/webpack-dev-server/client')]
          },
          {
            test: /.css$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  publicPath: '../',
                }
              }, 'css-loader', 'postcss-loader'],
          },
          {
            test: /.scss$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  publicPath: '../',
                }
              }, 'css-loader', 'postcss-loader', 'sass-loader'],
            exclude: /node_modules/
          }
        ]
      },
      plugins: [
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
          filename: 'css/[name].[hash].css',
          chunkFilename: 'css/[name].[hash].css',
        })
      ]
    })
    复制代码
      webpack.config.js
    
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')   //这里引入插件
    const vueLoaderPlugin = require('vue-loader/lib/plugin')
    const CopyWebpackPlugin = require('copy-webpack-plugin')      // 复制文件
    
    function resolve(dir) {
      return path.join(__dirname, '..', dir)
    }
    
    module.exports = {
      mode: 'development',
      entry: path.resolve(__dirname, '../src/main.js'),
      output: {
        filename: 'js/[name].[hash:8].js',
        path: path.resolve(__dirname, '../dist'),
        chunkFilename: 'js/[name].[hash:8].js',  //异步加载模块
        publicPath: './'
      },
      externals: {},
      module: {
        noParse: /jquery/,
        rules: [
          {
            test: /.vue$/,
            use: [{
              loader: 'vue-loader',
              options: {
                compilerOptions: {
                  preserveWhitespace: false
                }
              }
            }]
          },
          {
            test: /.(jpe?g|png|gif)$/i, //图片文件
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 10240,
                  fallback: {
                    loader: 'file-loader',
                    options: {
                      name: 'img/[name].[hash:8].[ext]',
                      publicPath: '../'
                    }
                  }
                }
              }
            ]
          },
          {
            test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/, //媒体文件
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 10240,
                  fallback: {
                    loader: 'file-loader',
                    options: {
                      name: 'media/[name].[hash:8].[ext]',
                      publicPath: '../'
                    }
                  }
                }
              }
            ]
          },
          {
            test: /.(woff2?|eot|ttf|otf)(?.*)?$/i, // 字体
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 10240,
                  fallback: {
                    loader: 'file-loader',
                    options: {
                      name: 'font/[name].[hash:8].[ext]',
                      publicPath: '../'
                    }
                  }
                }
              }
            ]
          }
        ]
      },
      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js',
          '@': resolve('src'),
        },
        extensions: ['.js', '.vue', '.json'],
      },
      //插件注入
      plugins: [
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, '../public/index.html')
        }),
        new vueLoaderPlugin(),
        new CopyWebpackPlugin({
          patterns: [
            {
              from: path.resolve(__dirname, '../public'),
              to: path.resolve(__dirname, '../dist')
            }
          ]
        })
      ]
    }复制代码

    3.webpack配置优化

    1.设置mode

    默认为production,webpack4.x默认会压缩代码和去除无用的代码

    可选参数:production, development

    ps:之前我认为只需要设置mode为production,就不用使用压缩css和js的插件,但结果发现我错了,仔细比较了下,还是要安装的

    先安装打包css的:

    npm i -D optimize-css-assets-webpack-plugin复制代码
    webpack.prod.js
    
    const optimizeCss = require('optimize-css-assets-webpack-plugin');
    
    plugins:[
      new optimizeCss({
          cssProcessor: require('cssnano'), //引入cssnano配置压缩选项
          cssProcessorOptions: {
            discardComments: { removeAll: true }
          },
          canPrint: true //是否将插件信息打印到控制台
      })
    ]
    复制代码

    压缩js和js打包多线程的暂时没有添加,在网上搜有的说不用添加,有的说还是要安装插件,等实际项目中我用完之后再来添加

    2.缩小搜索范围

     alias 可以告诉webpack去指定文件夹去寻找,尽量多使用
    
     include exclude    包括和过滤
    
     noParse   当我们代码中使用到import jq from 'jquery'时,webpack会去解析jq这个库是否有依赖其他的包。这个可以告诉webpack不必解析
    
     extensions    使用频率高的写在前面  
    复制代码

    3.单线程转多线程

    webpack处理文本,图片,css的时候,由于js单线程的特性,只能一个一个文件的处理,HappyPack可以将这个任务 分解到多个子线程里面,子线程完毕后会把结果发送到主线程,从而加快打包速度

    先安装:

    npm i -D happypack

    webpack.prod.js
    
    const HappyPack = require('happypack')     //单进程转多进程
    const os = require('os')
    const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
    
    module: {
        rules: [{
            test: /.js$/,
            use: ['happypack/loader?id=happyBabel'],
            exclude: /node_modules/,
            include: [resolve('src'), resolve('node_modules/webpack-dev-server/client')]
        }]
    }
    
    plugins:[
       new HappyPack({
          id: 'happyBabel',
          loaders: ['babel-loader?cacheDirectory'],
          threadPool: happyThreadPool
        })
    ]
    复制代码

    4.第三方模块优化

    将不怎么改变的第三方依赖,我们可以用DllPlugin DllReferencePlugin将它从依赖中抽离出来,这样每一次打包就不用打包这些文件,加快了打包的速度;

    但是webpack4.x的性能已经很好了,参考vue-cli也没有使用dll抽离,所以我们这里也不使用了,这里我们使用 另一个插件:hard-source-webpack-plugin ,这个插件会去对比修改了哪些配置,只去打包修改过了的配置 第一次打包速度正常,第二次打包速度能提升 50%+

    npm i -D hard-source-webpack-plugin
    
    webpack.prod.js
    
    const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')    //缓存第三方模块
    plugins: [
       new HardSourceWebpackPlugin()
    ]
    
    复制代码

    5.externals

    通过cdn加载的依赖,可以在这里设置,就不会通过webpack编译

    6.g-zip压缩

    g-zip压缩可以将已经压缩过的js,css再次压缩一遍,减少了打包大小,需要nginx配置

    npm i -D compression-webpack-plugin
    
    webpack.prod.js
    
    const CompressionWebpackPlugin = require('compression-webpack-plugin')
    const productionGzipExtensions = ["js", "css"];
    
    plugins:[
       new CompressionWebpackPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: new RegExp("\.(" + productionGzipExtensions.join("|") + ")$"),
          threshold: 10240, // 只有大小大于10k的资源会被处理
          minRatio: 0.6 // 压缩比例,值为0 ~ 1
        })
    ]
    
    复制代码

    7.自动获取本地Ip,通过本地ip地址启动项目

    webpack.dev.js
    
    const os = require('os')
    devServer:{
      host:()=>{
          var netWork = os.networkInterfaces()
          var ip = ''
          for (var dev in netWork) {
              netWork[dev].forEach(function (details) {
                  if (ip === '' && details.family === 'IPv4' && !details.internal) {
                     ip = details.address
                     return;
                  }
              })
         }
            return ip || 'localhost'
       }
    }
    
    复制代码

    8.抽离一些公共配置

    根目录新建vue.config.js 里面配置一些公共的配置如:

    const os = require('os')
    
    module.exports = {
      dev: {
        host: getNetworkIp(),   //端口号
        port: 8999,
        autoOpen: true,  //自动打开
      },
      build: {
        productionGzipExtensions: ["js", "css"],  //需要开启g-zip的文件后缀
        productionGzip: false     //是否开启g-zip压缩
      }
    }
    
    //获取本地ip地址
    function getNetworkIp() {
      var netWork = os.networkInterfaces()
      var ip = ''
      for (var dev in netWork) {
        netWork[dev].forEach(function (details) {
          if (ip === '' && details.family === 'IPv4' && !details.internal) {
            ip = details.address
            return;
          }
        })
      }
      return ip || 'localhost'
    }
    
    然后webpack.dev.js  webpack.prod.js引入这个文件,获取其中的配置就好了
    
    复制代码

    9.打包大小分析

    先安装:

    npm i -D webpack-bundle-analyzer

    webpack.prod.js
    
    if (process.env.npm_config_report) {
      const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
      prodConfig.plugins.push(
        new BundleAnalyzerPlugin()
      )
    }
    
    然后 npm run build --report就会弹出一个页面,里面就是打包大小分析
    
    复制代码

    10.完整的vue项目(vue-router axios vuex等)

    先安装:

    npm i -S vue-router axios vuex

    然后在src里面新建 -> router文件夹 ->新建index.js

    index.js
    
    import Vue from "vue"
    import Router from "vue-router"
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'hash',
      routes: [
        {
          path: '/',
          name: 'home',
          component: () => import(/* webpackChunkName: "home" */ "@/views/home"),
        },
      ]
    })
    
    main.js
    
    import router from "./router"
    new Vue({
      router,
      render: h => h(App)
    }).$mount('#app')
    
    新建views -> Home.vue
    
    随便写点东西,然后npm run dev  这样就完成了一个路由了
    
    复制代码

    到这里webpack搭建vue项目就搭建完成,还有没懂的吗?光理论是不够的。在此赠送2020最新企业级 Vue3.0/Js/ES6/TS/React/node等实战视频教程,想学的可进裙 519293536 免费获取,小白勿进哦!

    本文的文字及图片来源于网络加上自己的想法,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/chengxuyuanaa/p/13068686.html
Copyright © 2011-2022 走看看