• 14. vue源码入口+项目结构分析


    一. vue源码

    我们安装好vue以后, 如何了解vue的的代码结构, 从哪里下手呢?

    1.1. vue源码入口

    vue的入口是package.json

    来分别看看是什么含义

    • dependences:
      "dependencies": {
        "vue": "^2.5.2"
      },
    

    这段代码告诉我们vue的版本: 2.5.2

    • engines
      "engines": {
        "node": ">= 6.0.0",
        "npm": ">= 3.0.0"
      },
    

    指定当前node的版本和npm的版本

    • devDependencies
      里面是引入的各种loader

    • scripts

      "scripts": {
        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "start": "npm run dev",
        "build": "node build/build.js"
      },
    

    这就是重点了。 我们npm run build、npm run dev都是执行这里面的命令。 他告诉我们当执行build的时候是在执行那个文件。

    1. dev: 读取的配置文件是build/webpack.dev.conf.js
    2. build: 读取的配置文件是buld/build.js

    1.2.项目文件的结构

    先来看看项目的整体目录结构

    1.2.1. webpack相关配置

    1.2.1.1 webpack.dev.config.js是本地开发环境读取配置文件。

    'use strict'
    // 定义变量, 生产环境和开发环境区别定义
    const utils = require('./utils')
    const webpack = require('webpack')
    const config = require('../config')
    const merge = require('webpack-merge')
    const path = require('path')
    // 引入公共配置
    const baseWebpackConfig = require('./webpack.base.conf')
    /**
     * 引入插件
     */
    // 版权插件
    const CopyWebpackPlugin = require('copy-webpack-plugin')
    // 打包html到dist文件下, 并自动引入main.js文件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    //友好的错误提示插件
    const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
    const portfinder = require('portfinder')
    
    const HOST = process.env.HOST
    const PORT = process.env.PORT && Number(process.env.PORT)
    
    // merge函数: 将两个配置和并. 这里是将基础配置和开发环境的配置进行合并
    const devWebpackConfig = merge(baseWebpackConfig, {
      module: {
        rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
      },
      // cheap-module-eval-source-map is faster for development
      devtool: config.dev.devtool,
    
      // these devServer options should be customized in /config/index.js
      devServer: {
        clientLogLevel: 'warning',
        historyApiFallback: {
          rewrites: [
            { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
          ],
        },
        hot: true,
        contentBase: false, // since we use CopyWebpackPlugin.
        compress: true,
        host: HOST || config.dev.host,
        port: PORT || config.dev.port,
        open: config.dev.autoOpenBrowser,
        overlay: config.dev.errorOverlay
          ? { warnings: false, errors: true }
          : false,
        publicPath: config.dev.assetsPublicPath,
        proxy: config.dev.proxyTable,
        quiet: true, // necessary for FriendlyErrorsPlugin
        watchOptions: {
          poll: config.dev.poll,
        }
      },
      // 开发环境引入的插件
      plugins: [
        new webpack.DefinePlugin({
          'process.env': require('../config/dev.env')
        }),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
        new webpack.NoEmitOnErrorsPlugin(),
        // https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({
          filename: 'index.html',
          template: 'index.html',
          inject: true
        }),
        // copy custom static assets
        new CopyWebpackPlugin([
          {
            from: path.resolve(__dirname, '../static'),
            to: config.dev.assetsSubDirectory,
            ignore: ['.*']
          }
        ])
      ]
    })
    
    module.exports = new Promise((resolve, reject) => {
      portfinder.basePort = process.env.PORT || config.dev.port
      portfinder.getPort((err, port) => {
        if (err) {
          reject(err)
        } else {
          // publish the new Port, necessary for e2e tests
          process.env.PORT = port
          // add port to devServer config
          devWebpackConfig.devServer.port = port
    
          // Add FriendlyErrorsPlugin
          devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
            compilationSuccessInfo: {
              messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
            },
            onErrors: config.dev.notifyOnErrors
            ? utils.createNotifierCallback()
            : undefined
          }))
    
          resolve(devWebpackConfig)
        }
      })
    })
    
    
    
    • webpack.base.conf: 引入了基础项目配置。 公共的配置文件(开发和生产都会使用到的配置文件)都写到这里
    • 引入插件: 版权插件、html文件打包插件、有好错题提示插件
    • 引入merge包, 将基础配置文件和当前文件合并。

    1.2.1.2 build.js是build打包时读取的配置文件

    'use strict'
    require('./check-versions')()
    
    process.env.NODE_ENV = 'production'
    
    const ora = require('ora')
    const rm = require('rimraf')
    const path = require('path')
    const chalk = require('chalk')
    const webpack = require('webpack')
    const config = require('../config')
    // 引入了prod配置文件
    const webpackConfig = require('./webpack.prod.conf')
    
    ...
    

    我们看到build.js引入了webpack.prod.conf配置文件

    下面就来看看webpack.prod.conf配置文件都有哪些内容

    'use strict'
    // 生产环境个性化配置
    const path = require('path')
    const utils = require('./utils')
    // 引入webpack打包工具
    const webpack = require('webpack')
    const config = require('../config')
    // 引入配置合并工具
    const merge = require('webpack-merge')
    // 引入基础配置文件
    const baseWebpackConfig = require('./webpack.base.conf')
    // 引入版权配置插件
    const CopyWebpackPlugin = require('copy-webpack-plugin')
    // 引入html配置合并
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    // 引入text打包工具
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    // 引入css打包工具
    const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
    // 引入js压缩工具
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    
    // 引入生产环境的配置文件
    const env = require('../config/prod.env')
    
    // merge: 将基础配置 + 生产的个性化配置合并
    const webpackConfig = merge(baseWebpackConfig, {
      module: {
        rules: utils.styleLoaders({
          sourceMap: config.build.productionSourceMap,
          extract: true,
          usePostCSS: true
        })
      },
      devtool: config.build.productionSourceMap ? config.build.devtool : false,
      output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
      },
      // 生成环境需要使用的插件
      plugins: [
        // http://vuejs.github.io/vue-loader/en/workflow/production.html
        new webpack.DefinePlugin({
          'process.env': env
        }),
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              warnings: false
            }
          },
          sourceMap: config.build.productionSourceMap,
          parallel: true
        }),
        // extract css into its own file
        new ExtractTextPlugin({
          filename: utils.assetsPath('css/[name].[contenthash].css'),
          // Setting the following option to `false` will not extract CSS from codesplit chunks.
          // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
          // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
          // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
          allChunks: true,
        }),
        // Compress extracted CSS. We are using this plugin so that possible
        // duplicated CSS from different components can be deduped.
        new OptimizeCSSPlugin({
          cssProcessorOptions: config.build.productionSourceMap
            ? { safe: true, map: { inline: false } }
            : { safe: true }
        }),
        // generate dist index.html with correct asset hash for caching.
        // you can customize output by editing /index.html
        // see https://github.com/ampedandwired/html-webpack-plugin
        // html打包插件: 比如:将index.html打包到dist文件夹中.并自动引入bundle.js文件
        new HtmlWebpackPlugin({
          filename: config.build.index,
          template: 'index.html',
          inject: true,
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
            // more options:
            // https://github.com/kangax/html-minifier#options-quick-reference
          },
          // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          chunksSortMode: 'dependency'
        }),
        // keep module.id stable when vendor modules does not change
        new webpack.HashedModuleIdsPlugin(),
        // enable scope hoisting
        new webpack.optimize.ModuleConcatenationPlugin(),
        // split vendor js into its own file
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          minChunks (module) {
            // any required modules inside node_modules are extracted to vendor
            return (
              module.resource &&
              /.js$/.test(module.resource) &&
              module.resource.indexOf(
                path.join(__dirname, '../node_modules')
              ) === 0
            )
          }
        }),
        // 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',
          minChunks: Infinity
        }),
        // This instance extracts shared chunks from code splitted chunks and bundles them
        // in a separate chunk, similar to the vendor chunk
        // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
        new webpack.optimize.CommonsChunkPlugin({
          name: 'app',
          async: 'vendor-async',
          children: true,
          minChunks: 3
        }),
    
        // copy custom static assets
        new CopyWebpackPlugin([
          {
            from: path.resolve(__dirname, '../static'),
            to: config.build.assetsSubDirectory,
            ignore: ['.*']
          }
        ])
      ]
    })
    
    if (config.build.productionGzip) {
      const CompressionWebpackPlugin = require('compression-webpack-plugin')
    
      webpackConfig.plugins.push(
        new CompressionWebpackPlugin({
          asset: '[path].gz[query]',
          algorithm: 'gzip',
          test: new RegExp(
            '\.(' +
            config.build.productionGzipExtensions.join('|') +
            ')$'
          ),
          threshold: 10240,
          minRatio: 0.8
        })
      )
    }
    
    if (config.build.bundleAnalyzerReport) {
      const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
      webpackConfig.plugins.push(new BundleAnalyzerPlugin())
    }
    
    module.exports = webpackConfig
    
    • 这prod.config.js中引入了webpack.base.conf
    • 引入了一些插件: 版权配置插件, html打包插件,text打包工具、css打包压缩工具、js压缩工具。
    • 读取了config/prod.env配置文件。
    • 使用merge合并基础配置

    1.2.2 .babelrc配置文件:ES代码相关转化配置

    {
      "presets": [
        ["env", {
          "modules": false,
          "targets": {
            "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
          }
        }],
        "stage-2"
      ],
      "plugins": ["transform-vue-jsx", "transform-runtime"]
    }
    

    这是将es6的语法转换成es5. 转换的目标是什么呢

    "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
    
    1. 市场份额大于1%
    2. 转换浏览器的最后两个版本
    3. ie8以下的版本不转化

    1.2.3 .editorconfig文本编辑相关配置

    root = true
    
    [*]
    charset = utf-8
    indent_style = space
    indent_size = 2
    end_of_line = lf
    insert_final_newline = true
    trim_trailing_whitespace = true
    
    
    • charset: 配置文本的字符编码格式
    • indent_style: 默认的缩进方式是空格
    • indent_size: 缩进空格数是2个
    • end_of_line: 尾部处理方式
    • insert_final_newline: 尾部自动增加一个单行
    • trim_trailing_whitespace: 是否自动格式化空格

    1.2.4 .eslintrc.js esLint相关的设置

    esLint格式化内容配置, 我们可以启动或者关闭eslint.

    1.3. vue访问入口

    vue的访问入口是index.html, 当我们执行

    npm run dev
    

    的时候, 其实是将文件打包的过程, 和npm run build的区别是, 它是将文件打包到内存。 然后运行在本地服务器。而npm run build是打包到磁盘dist文件夹

    1.3.1 访问入口

    vue访问的入口是main.js

    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
    })
    
    
    • 引入了vue
    • 引入了./App.vue, 当前目录的App.vue配置文件
    • 当前vue的作用dom元素是id="app"的元素
    • 引入了App组件。 App组件,定义在App.vue中
    • 使用App组件替代id="app"的元素。

    下面来看看App.vue

    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <HelloWorld/>
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      }
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    • 首先引入了HelloWorld组件
    import HelloWorld from './components/HelloWorld'
    
    • 将组件注册到名为App的组件中
    • 在模板中引入HelloWorld组件

    然后,我们就看到vue首页的效果了。了解源码入口,方便我们后续代码.



  • 相关阅读:
    通过windows server使用frp软件实现内网穿透
    【Java】使用线程解决生产者与消费者问题
    WindowsServers2019摄像头不可用的解决方案
    【CSS】复杂三栏布局
    【Java】TCP发送与接收数据
    【Java】UDP发送数据与接收数据
    【CSS】三栏布局
    【CSS】实现两栏布局
    JS获取url参数
    Centos 安装Tcl
  • 原文地址:https://www.cnblogs.com/ITPower/p/14498165.html
Copyright © 2020-2023  润新知