vue-cli webpack配置文件分析


Posted in Javascript onMay 20, 2019

相信vue使用者对vue-cli都不会陌生,甚至可以说,很熟悉了,但对其webpack的配置可能知之甚少吧。

过完年回来后,我接手了公司的新项目。新项目是一个spa。很自然,我就想到了vue-cli脚手架了,当时研究一下它的webpack配置。于是,就有了其他的内容。

今天这篇文章,是在原来的基础上,增加了一些新版本的内容,但实质上变化不大。

说明

此仓库为vue-cli webpack的配置分析,其实只是在源码中加上注释而已。大家查看详细分析,可以从后面提到的入口文件开始查看。

分析不包括check-versions.js文件,因为check-versions.js是检测npm和node版本,不涉及webpack,所以就没有对check-versions.js进行分析。同时,也不包括测试部分的代码,该分析只是针对开发和生产环境的webpack配置进行分析。

vue-cli 版本

2.8.1

入口

从package.json可以看到开发和生产环境的入口。

"scripts": {
  "dev": "node build/dev-server.js",
  "build": "node build/build.js"
 }

开发环境

开发环境的入口文件是 build/dev-server.js。

dev-server.js

该文件中,使用express作为后端框架,结合一些关于webpack的中间件,搭建了一个开发环境。

// 配置文件
var config = require('../config')
// 如果 Node 的环境无法判断当前是 dev / product 环境
// 使用 config.dev.env.NODE_ENV 作为当前的环境
if (!process.env.NODE_ENV) {
 process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}

// 可以强制打开浏览器并跳转到指定 url 的插件
// https://github.com/sindresorhus/opn
var opn = require('opn')
// node自带的文件路径工具
var path = require('path')
// express框架
var express = require('express')
var webpack = require('webpack')
// 测试环境,使用的配置与生产环境的配置一样
// 非测试环境,即为开发环境,因为此文件只有测试环境和开发环境使用
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = process.env.NODE_ENV === 'testing'
// 生产环境配置文件
 ? require('./webpack.prod.conf')
 // 开发环境配置文件
 : require('./webpack.dev.conf')

// 端口号为命令行输入的PORT参数或者配置文件中的默认值
var port = process.env.PORT || config.dev.port
// 配置文件中 是否自动打开浏览器
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// 配置文件中 http代理配置
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable

// 启动 express 服务
var app = express()
// 启动 webpack 编译
var compiler = webpack(webpackConfig)

// 可以将编译后的文件暂存到内存中的插件
// https://github.com/webpack/webpack-dev-middleware
var devMiddleware = require('webpack-dev-middleware')(compiler, {
 // 公共路径,与webpack的publicPath一样
 publicPath: webpackConfig.output.publicPath,
 // 不打印
 quiet: true
})

// Hot-reload 热重载插件
// https://github.com/glenjamin/webpack-hot-middleware
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
 log: () => {}
})
// 当tml-webpack-plugin template更改之后,强制刷新浏览器
compiler.plugin('compilation', function (compilation) {
 compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
  hotMiddleware.publish({ action: 'reload' })
  cb()
 })
})

// 将 proxyTable 中的请求配置挂在到启动的 express 服务上
Object.keys(proxyTable).forEach(function (context) {
 var options = proxyTable[context]
 // 如果options的数据类型为string,则表示只设置了url,
 // 所以需要将url设置为对象中的 target的值
 if (typeof options === 'string') {
  options = { target: options }
 }
 app.use(proxyMiddleware(options.filter || context, options))
})

// 使用 connect-history-api-fallback 匹配资源
// 如果不匹配就可以重定向到指定地址
// https://github.com/bripkens/connect-history-api-fallback
app.use(require('connect-history-api-fallback')())

// 将暂存到内存中的 webpack 编译后的文件挂在到 express 服务上
app.use(devMiddleware)

// 将 Hot-reload 挂在到 express 服务上
app.use(hotMiddleware)

// 拼接 static 文件夹的静态资源路径
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// 静态文件服务
app.use(staticPath, express.static('./static'))

var uri = 'http://localhost:' + port

// 编译成功后打印网址信息
devMiddleware.waitUntilValid(function () {
 console.log('> Listening at ' + uri + '\n')
})

module.exports = app.listen(port, function (err) {
 if (err) {
  console.log(err)
  return
 }

 // 如果配置了自动打开浏览器,且不是测试环境,则自动打开浏览器并跳到我们的开发地址
 if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
  opn(uri)
 }
})

webpack.dev.conf.js

dev-server.js中使用了webpack.dev.conf.js文件,该文件是开发环境中webpack的配置入口。

// 工具函数集合
var utils = require('./utils')
var webpack = require('webpack')
 // 配置文件
var config = require('../config')
 // webpack 配置合并插件
var merge = require('webpack-merge')
 // webpac基本配置
var baseWebpackConfig = require('./webpack.base.conf')
 // 自动生成 html 并且注入到 .html 文件中的插件
 // https://github.com/ampedandwired/html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin')
 // webpack错误信息提示插件
 // https://github.com/geowarin/friendly-errors-webpack-plugin
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// 将 Hol-reload 热重载的客户端代码添加到 webpack.base.conf 的 对应 entry 中,一起打包
Object.keys(baseWebpackConfig.entry).forEach(function(name) {
 baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
 module: {
  // styleLoaders
  rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
 },
 // 最新的配置为 cheap-module-eval-source-map,虽然 cheap-module-eval-source-map更快,但它的定位不准确
 // 所以,换成 eval-source-map
 devtool: '#eval-source-map',
 plugins: [
  // definePlugin 接收字符串插入到代码当中, 所以你需要的话可以写上 JS 的字符串
  // 此处,插入适当的环境
  // https://webpack.js.org/plugins/define-plugin/
  new webpack.DefinePlugin({
   'process.env': config.dev.env
  }),
  // HotModule 插件在页面进行变更的时候只会重绘对应的页面模块,不会重绘整个 html 文件
  // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoEmitOnErrorsPlugin(),
  // 将 index.html 作为入口,注入 html 代码后生成 index.html文件
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: 'index.html',
   template: 'index.html',
   inject: true
  }),
  // webpack错误信息提示插件
  new FriendlyErrorsPlugin()
 ]
})

webpack.base.conf.js

在webpack.dev.conf.js中出现webpack.base.conf.js,这个文件是开发环境和生产环境,甚至测试环境,这些环境的公共webpack配置。可以说,这个文件相当重要。

// node自带的文件路径工具
var path = require('path')
// 工具函数集合
var utils = require('./utils')
 // 配置文件
var config = require('../config')
 // 工具函数集合
var vueLoaderConfig = require('./vue-loader.conf')

/**
 * 获得绝对路径
 * @method resolve
 * @param {String} dir 相对于本文件的路径
 * @return {String}   绝对路径
 */
function resolve(dir) {
 return path.join(__dirname, '..', dir)
}

module.exports = {
 entry: {
  app: './src/main.js'
 },
 output: {
  // 编译输出的静态资源根路径
  path: config.build.assetsRoot,
  // 编译输出的文件名
  filename: '[name].js',
  // 正式发布环境下编译输出的上线路径的根路径
  publicPath: process.env.NODE_ENV === 'production' ?
   config.build.assetsPublicPath : config.dev.assetsPublicPath
 },
 resolve: {
  // 自动补全的扩展名
  extensions: ['.js', '.vue', '.json'],
  // 路径别名
  alias: {
   // 例如 import Vue from 'vue',会自动到 'vue/dist/vue.common.js'中寻找
   'vue$': 'vue/dist/vue.esm.js',
   '@': resolve('src'),
  }
 },
 module: {
  rules: [{
    // 审查 js 和 vue 文件
    // https://github.com/MoOx/eslint-loader
    test: /\.(js|vue)$/,
    loader: 'eslint-loader',
    // 表示预先处理
    enforce: "pre",
    include: [resolve('src'), resolve('test')],
    options: {
     formatter: require('eslint-friendly-formatter')
    }
   },
   {
    // 处理 vue文件
    // https://github.com/vuejs/vue-loader
    test: /\.vue$/,
    loader: 'vue-loader',
    options: vueLoaderConfig
   },
   {
    // 编译 js
    // https://github.com/babel/babel-loader
    test: /\.js$/,
    loader: 'babel-loader',
    include: [resolve('src'), resolve('test')]
   },
   {
    // 处理图片文件
    // https://github.com/webpack-contrib/url-loader
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    query: {
     limit: 10000,
     name: utils.assetsPath('img/[name].[hash:7].[ext]')
    }
   },
   {
    // 处理字体文件
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
     limit: 10000,
     name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
    }
   }
  ]
 }
}

config/index.js

该文件在很多文件中都用到,是主要的配置文件,包含静态文件的路径、是否开启sourceMap等。其中,分为两个部分dev(开发环境的配置)和build(生产环境的配置)。

// 详情见文档:https://vuejs-templates.github.io/webpack/env.html
var path = require('path')

module.exports = {
 // production 生产环境
 build: {
  // 构建环境
  env: require('./prod.env'),
  // 构建输出的index.html文件
  index: path.resolve(__dirname, '../dist/index.html'),
  // 构建输出的静态资源路径
  assetsRoot: path.resolve(__dirname, '../dist'),
  // 构建输出的二级目录
  assetsSubDirectory: 'static',
  // 构建发布的根目录,可配置为资源服务器域名或 CDN 域名
  assetsPublicPath: '/',
  // 是否开启 cssSourceMap
  productionSourceMap: true,
  // Gzip off by default as many popular static hosts such as
  // Surge or Netlify already gzip all static assets for you.
  // Before setting to `true`, make sure to:
  // npm install --save-dev compression-webpack-plugin
  // 默认关闭 gzip,因为很多流行的静态资源主机,例如 Surge、Netlify,已经为所有静态资源开启gzip
  productionGzip: false,
  // 需要使用 gzip 压缩的文件扩展名
  productionGzipExtensions: ['js', 'css'],
  // Run the build command with an extra argument to
  // View the bundle analyzer report after build finishes:
  // `npm run build --report`
  // Set to `true` or `false` to always turn it on or off
  // 运行“build”命令行时,加上一个参数,可以在构建完成后参看包分析报告
  // true为开启,false为关闭
  bundleAnalyzerReport: process.env.npm_config_report
 },
 // dev 开发环境
 dev: {
  // 构建环境
  env: require('./dev.env'),
  // 端口号
  port: 3333,
  // 是否自动打开浏览器
  autoOpenBrowser: true,
  assetsSubDirectory: 'static',
  // 编译发布的根目录,可配置为资源服务器域名或 CDN 域名
  assetsPublicPath: '/',
  // proxyTable 代理的接口(可跨域)
  // 使用方法:https://vuejs-templates.github.io/webpack/proxy.html
  proxyTable: {},
  // CSS Sourcemaps off by default because relative paths are "buggy"
  // with this option, according to the CSS-Loader README
  // (https://github.com/webpack/css-loader#sourcemaps)
  // In our experience, they generally work as expected,
  // just be aware of this issue when enabling this option.
  // 默认情况下,关闭 CSS Sourcemaps,因为使用相对路径会报错。
  // CSS-Loader README:https://github.com/webpack/css-loader#sourcemaps
  cssSourceMap: false
 }
}

utils.js

utils.js也是一个被使用频率的文件,这个文件包含了三个工具函数:

  • 生成静态资源的路径
  • 生成 ExtractTextPlugin对象或loader字符串
  • 生成 style-loader的配置
// node自带的文件路径工具
var path = require('path')
// 配置文件
var config = require('../config')
// 提取css的插件
// https://github.com/webpack-contrib/extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')

/**
 * 生成静态资源的路径
 * @method assertsPath
 * @param {String}  _path 相对于静态资源文件夹的文件路径
 * @return {String}     静态资源完整路径
 */
exports.assetsPath = function (_path) {
 var assetsSubDirectory = process.env.NODE_ENV === 'production'
  ? config.build.assetsSubDirectory
  : config.dev.assetsSubDirectory
  // path.posix.join与path.join一样,不过总是以 posix 兼容的方式交互
 return path.posix.join(assetsSubDirectory, _path)
}

/**
 * 生成处理css的loaders配置
 * @method cssLoaders
 * @param {Object}  options 生成配置
 *              option = {
 *               // 是否开启 sourceMap
 *               sourceMap: true,
 *               // 是否提取css
 *               extract: true
 *              }
 * @return {Object}      处理css的loaders配置对象
 */
exports.cssLoaders = function (options) {
 options = options || {}

 var cssLoader = {
  loader: 'css-loader',
  options: {
   minimize: process.env.NODE_ENV === 'production',
   sourceMap: options.sourceMap
  }
 }
 /**
  * 生成 ExtractTextPlugin对象或loader字符串
  * @method generateLoaders
  * @param {Array}    loaders loader名称数组
  * @return {String|Object}    ExtractTextPlugin对象或loader字符串
  */
 function generateLoaders (loader, loaderOptions) {
  var loaders = [cssLoader]
  if (loader) {
   loaders.push({
    // 例如,sass?indentedSyntax
    // 在?号前加上“-loader”
    loader: loader + '-loader',
    options: Object.assign({}, loaderOptions, {
     sourceMap: options.sourceMap
    })
   })
  }

  // extract为true时,提取css
  // 生产环境中,默认为true
  if (options.extract) {
   return ExtractTextPlugin.extract({
    use: loaders,
    fallback: 'vue-style-loader'
   })
  } else {
   return ['vue-style-loader'].concat(loaders)
  }
 }

 // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
 return {
  css: generateLoaders(),
  postcss: generateLoaders(),
  less: generateLoaders('less'),
  sass: generateLoaders('sass', { indentedSyntax: true }),
  scss: generateLoaders('sass'),
  stylus: generateLoaders('stylus'),
  styl: generateLoaders('stylus')
 }
}

/**
 * 生成 style-loader的配置
 * style-loader文档:https://github.com/webpack/style-loader
 * @method styleLoaders
 * @param {Object}   options 生成配置
 *               option = {
 *                // 是否开启 sourceMap
 *                sourceMap: true,
 *                // 是否提取css
 *                extract: true
 *               }
 * @return {Array}       style-loader的配置
 */
exports.styleLoaders = function (options) {
 var output = []
 var loaders = exports.cssLoaders(options)
 for (var extension in loaders) {
  var loader = loaders[extension]
  output.push({
   test: new RegExp('\\.' + extension + '$'),
   use: loader
  })
 }
 return output
}

生产环境

开发环境的入口文件是build/build.js 。

build.js

该文件,为构建打包文件,会将源码进行构建(编译、压缩等)后打包。

// 设置当前环境为生产环境
process.env.NODE_ENV = 'production'

// loading 插件
// https://github.com/sindresorhus/ora
var ora = require('ora')
// 可以在 node 中执行`rm -rf`的工具
// https://github.com/isaacs/rimraf
var rm = require('rimraf')
// node自带的文件路径工具
var path = require('path')
// 在终端输出带颜色的文字
// https://github.com/chalk/chalk
var chalk = require('chalk')
var webpack = require('webpack')
// 配置文件
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')

// 在终端显示loading效果,并输出提示
var spinner = ora('building for production...')
spinner.start()

// 删除这个文件夹 (递归删除)
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
 if (err) throw err
 // 构建
 webpack(webpackConfig, function (err, stats) {
  // 构建成功

  // 停止 loading动画
  spinner.stop()
  if (err) throw err
  process.stdout.write(stats.toString({
   colors: true,
   modules: false,
   children: false,
   chunks: false,
   chunkModules: false
  }) + '\n\n')

  // 打印提示
  console.log(chalk.cyan(' Build complete.\n'))
  console.log(chalk.yellow(
   ' Tip: built files are meant to be served over an HTTP server.\n' +
   ' Opening index.html over file:// won\'t work.\n'
  ))
 })
})

webpack.prod.conf

该文件,为生产环境中webpack的配置入口。同时,它也依赖于前面提到的webpack.base.conf.js、utils.js和config/index.js。

// node自带的文件路径工具
var path = require('path')
// 工具函数集合
var utils = require('./utils')
var webpack = require('webpack')
// 配置文件
var config = require('../config')
// webpack 配置合并插件
var merge = require('webpack-merge')
// webpack 基本配置
var baseWebpackConfig = require('./webpack.base.conf')
// webpack 复制文件和文件夹的插件
// https://github.com/kevlened/copy-webpack-plugin
var CopyWebpackPlugin = require('copy-webpack-plugin')
// 自动生成 html 并且注入到 .html 文件中的插件
// https://github.com/ampedandwired/html-webpack-plugin
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 提取css的插件
// https://github.com/webpack-contrib/extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// webpack 优化压缩和优化 css 的插件
// https://github.com/NMFR/optimize-css-assets-webpack-plugin
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

// 如果当前环境为测试环境,则使用测试环境
// 否则,使用生产环境
var env = process.env.NODE_ENV === 'testing'
 ? require('../config/test.env')
 : config.build.env

var webpackConfig = merge(baseWebpackConfig, {
 module: {
  // styleLoaders
  rules: utils.styleLoaders({
   sourceMap: config.build.productionSourceMap,
   extract: true
  })
 },
 // 是否开启 sourceMap
 devtool: config.build.productionSourceMap ? '#source-map' : false,
 output: {
  // 编译输出的静态资源根路径
  path: config.build.assetsRoot,
  // 编译输出的文件名
  filename: utils.assetsPath('js/[name].[chunkhash].js'),
  // 没有指定输出名的文件输出的文件名
  chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
 },
 plugins: [
  // definePlugin 接收字符串插入到代码当中, 所以你需要的话可以写上 JS 的字符串
  // 此处,插入适当的环境
  // http://vuejs.github.io/vue-loader/en/workflow/production.html
  new webpack.DefinePlugin({
   'process.env': env
  }),
  // 压缩 js
  new webpack.optimize.UglifyJsPlugin({
   compress: {
    warnings: false
   },
   sourceMap: true
  }),
  // 提取 css
  new ExtractTextPlugin({
   filename: utils.assetsPath('css/[name].[contenthash].css')
  }),
  // 压缩提取出来的 css
  // 可以删除来自不同组件的冗余代码
  // Compress extracted CSS. We are using this plugin so that possible
  // duplicated CSS from different components can be deduped.
  new OptimizeCSSPlugin(),
  // 将 index.html 作为入口,注入 html 代码后生成 index.html文件
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: process.env.NODE_ENV === 'testing'
    ? 'index.html'
    : config.build.index,
   template: 'index.html',
   inject: true,
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
    // 更多选项 https://github.com/kangax/html-minifier#options-quick-reference
   },
   // 必须通过 CommonsChunkPlugin一致地处理多个 chunks
   chunksSortMode: 'dependency'
  }),
  // 分割公共 js 到独立的文件
  // https://webpack.js.org/guides/code-splitting-libraries/#commonschunkplugin
  new webpack.optimize.CommonsChunkPlugin({
   name: 'vendor',
   minChunks: function (module, count) {
    // node_modules中的任何所需模块都提取到vendor
    return (
     module.resource &&
     /\.js$/.test(module.resource) &&
     module.resource.indexOf(
      path.join(__dirname, '../node_modules')
     ) === 0
    )
   }
  }),
  // 将webpack runtime 和模块清单 提取到独立的文件,以防止当 app包更新时导致公共 jsd hash也更新
  // extract webpack runtime and module manifest to its own file in order to
  // prevent vendor hash from being updated whenever app bundle is updated
  new webpack.optimize.CommonsChunkPlugin({
   name: 'manifest',
   chunks: ['vendor']
  }),
  // 复制静态资源
  // https://github.com/kevlened/copy-webpack-plugin
  new CopyWebpackPlugin([
   {
    from: path.resolve(__dirname, '../static'),
    to: config.build.assetsSubDirectory,
    ignore: ['.*']
   }
  ])
 ]
})

// 开启 gzip 的情况时,给 webpack plugins添加 compression-webpack-plugin 插件
if (config.build.productionGzip) {
  // webpack 压缩插件
  // https://github.com/webpack-contrib/compression-webpack-plugin
 var CompressionWebpackPlugin = require('compression-webpack-plugin')

 // 向webpackconfig.plugins中加入下方的插件
 webpackConfig.plugins.push(
  new CompressionWebpackPlugin({
   asset: '[path].gz[query]',
   algorithm: 'gzip',
   test: new RegExp(
    '\\.(' +
    config.build.productionGzipExtensions.join('|') +
    ')$'
   ),
   threshold: 10240,
   minRatio: 0.8
  })
 )
}

// 开启包分析的情况时, 给 webpack plugins添加 webpack-bundle-analyzer 插件
if (config.build.bundleAnalyzerReport) {
 // https://github.com/th0r/webpack-bundle-analyzer
 var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
 webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

其他

如果你觉得在segmentfault的代码阅读体验不好,你可以到我github上将代码clone下来看。

vue-cli-webpack-analysis

总结

这次研究webpack配置的时候,我自己跟着源码敲了一遍(很笨的方法),然后,在github和webpack官网上查使用到的插件的作用和用法。经过这一次折腾,加深对webpack的认识。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
拖动Html元素集合 Drag and Drop any item
Dec 22 Javascript
一个js的tab切换效果代码[代码分离]
Apr 11 Javascript
JS判断页面加载状态以及添加遮罩和缓冲动画的代码
Oct 11 Javascript
Jquery 实现表格颜色交替变化鼠标移过颜色变化实例
Aug 28 Javascript
不提示直接关闭网页窗口的JS示例代码
Dec 17 Javascript
javascript密码强度校验代码(两种方法)
Aug 10 Javascript
JS实现仿微博可关闭弹出层效果
Sep 21 Javascript
jquery彩色投票进度条简单实例演示
Jul 23 Javascript
webpack 模块热替换原理
Apr 09 Javascript
JavaScript+Canvas实现彩色图片转换成黑白图片的方法分析
Jul 31 Javascript
jQuery层叠选择器用法实例分析
Jun 28 jQuery
Javascript中window.name属性详解
Nov 19 Javascript
微信小程序开发之左右分栏效果的实例代码
May 20 #Javascript
微信小程序rich-text富文本用法实例分析
May 20 #Javascript
bootstrap中的导航条实例代码详解
May 20 #Javascript
详解小程序云开发数据库
May 20 #Javascript
VUE脚手架具体使用方法
May 20 #Javascript
Vue CLI2升级至Vue CLI3的方法步骤
May 20 #Javascript
解决Vue+Electron下Vuex的Dispatch没有效果问题
May 20 #Javascript
You might like
无JS,完全php面向过程数据分页实现代码
2012/08/27 PHP
一个PHP的远程图片抓取函数分享
2013/09/25 PHP
php实现将数组转换为XML的方法
2015/03/09 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
2016/04/26 PHP
PHP实现微信小程序人脸识别刷脸登录功能
2018/05/24 PHP
javascript权威指南 学习笔记之变量作用域分享
2011/09/28 Javascript
一个js导致的jquery失效问题的解决方法
2013/11/27 Javascript
jquery.validate.js插件使用经验记录
2014/07/02 Javascript
javascript实现淘宝幻灯片广告展示效果
2015/04/27 Javascript
JavaScript学习笔记之ES6数组方法
2016/03/25 Javascript
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
2016/11/21 NodeJs
jQuery插件HighCharts绘制2D圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
2017/09/20 jQuery
详解如何让Express支持async/await
2017/10/09 Javascript
prototype.js简单实现ajax功能示例
2017/10/18 Javascript
基于vue-cli创建的项目的目录结构及说明介绍
2017/11/23 Javascript
简易Vue评论框架的实现(父组件的实现)
2018/01/08 Javascript
详解vue 组件的实现原理
2020/11/12 Javascript
[44:40]Serenity vs Pain 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
使用python检测手机QQ在线状态的脚本代码
2013/02/10 Python
Python入门篇之列表和元组
2014/10/17 Python
Python中常用操作字符串的函数与方法总结
2016/02/04 Python
Python读取excel中的图片完美解决方法
2018/07/27 Python
用python写一个定时提醒程序的实现代码
2019/07/22 Python
python关闭占用端口方式
2019/12/17 Python
python手写均值滤波
2020/02/19 Python
Python将二维列表list的数据输出(TXT,Excel)
2020/04/23 Python
matplotlib 三维图表绘制方法简介
2020/09/20 Python
使用PyCharm官方中文语言包汉化PyCharm
2020/11/18 Python
如何用border-image实现文字气泡边框的示例代码
2020/01/21 HTML / CSS
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
《草原》教学反思
2014/02/15 职场文书
王老吉广告词
2014/03/20 职场文书
自信主题班会
2015/08/14 职场文书
清明节随笔
2015/08/15 职场文书
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP