webpack启动本地服务干了什么

场景

vue3、webpack、vue-cli

npm run serve步骤

1.npm run serve

npm run xxx 就是执行package.json.scripts.xxx 对应值为vue-cli-service serve接下来就找到vue-cli-service命令行文件,如下图:

找到对应的vue-cli-service.js文件如下图:

主要就是创建了一个Service类的实例,并且调用了实例的run方法,接下来看看这个Service实例是怎么写的

2.Service类

js 复制代码
//   ../lib/Service.js
module.exports = class Service {
  constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
    process.VUE_CLI_SERVICE = this
    this.initialized = false
    this.context = context
    this.inlineOptions = inlineOptions
    this.webpackChainFns = []
    this.webpackRawConfigFns = []
    this.devServerConfigFns = []
    this.commands = {}
    // Folder containing the target package.json for plugins
    this.pkgContext = context
    // package.json containing the plugins
    this.pkg = this.resolvePkg(pkg)
    // If there are inline plugins, they will be used instead of those
    // found in package.json.
    // When useBuiltIn === false, built-in plugins are disabled. This is mostly
    // for testing.
    this.plugins = this.resolvePlugins(plugins, useBuiltIn)
    // pluginsToSkip will be populated during run()
    this.pluginsToSkip = new Set()
    // resolve the default mode to use for each command
    // this is provided by plugins as module.exports.defaultModes
    // so we can get the information without actually applying the plugin.
    this.modes = this.plugins.reduce((modes, { apply: { defaultModes } }) => {
      return Object.assign(modes, defaultModes)
    }, {})
  }

async run (name, args = {}, rawArgv = []) {
    // resolve mode
    // prioritize inline --mode
    // fallback to resolved default modes from plugins or development if --watch is defined
    const mode = args.mode || (name === 'build' && args.watch ? 'development' : this.modes[name])

    // --skip-plugins arg may have plugins that should be skipped during init()
    this.setPluginsToSkip(args, rawArgv)

    // load env variables, load user config, apply plugins
    await this.init(mode)

    args._ = args._ || []
    let command = this.commands[name]
    if (!command && name) {
      error(`command "${name}" does not exist.`)
      process.exit(1)
    }
    if (!command || args.help || args.h) {
      command = this.commands.help
    } else {
      args._.shift() // remove command itself
      rawArgv.shift()
    }
    console.log('fn',command);
    const { fn } = command
    return fn(args, rawArgv)
  }
......一些内置的方法
}

遗留问题 根据上面代码可以得出:service.run(name,args,rawArgv)(这里留个坑,不太明白args具体参数是什么),const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())主要是不知道这个process全局变量怎么生成的,我查了下资料但是还是不明白,资料上面大致意思:

在 Vue CLI 项目中,process 对象的模拟不是通过源代码直接构建的,而是通过 webpack 的配置来实现的。具体来说,process 对象的模拟是在 webpack 的配置文件中使用 DefinePlugin 插件来完成的。

但是我是一开始run serve服务我是一步一步跟过来的,没有跳过一步,他怎么就给在Service类声明的文件里面就就有了process全局变量,我真不明白,后面再来填这个坑。

接下来看看run函数,首先根据传进来的是'build'还是'serve'设置mode变量,然后执行init(mode),最后返回一个函数,这个函数目前没看到有调用,暂时按下不表,那么接下来看看init函数

js 复制代码
  init (mode = process.env.VUE_CLI_MODE) {
    
    if (this.initialized) {
      return
    }
    this.initialized = true
    this.mode = mode
 
    // load mode .env
    if (mode) {
      this.loadEnv(mode)
    }
    // load base .env
    this.loadEnv()

    // load user config
    const userOptions = this.loadUserOptions()
    const loadedCallback = (loadedUserOptions) => {
      this.projectOptions = defaultsDeep(loadedUserOptions, defaults())

      debug('vue:project-config')(this.projectOptions)

      // apply plugins.
      this.plugins.forEach(({ id, apply }) => {
        if (this.pluginsToSkip.has(id)) return
        apply(new PluginAPI(id, this), this.projectOptions)
      })

      // apply webpack configs from project config file
      if (this.projectOptions.chainWebpack) {
        this.webpackChainFns.push(this.projectOptions.chainWebpack)
      }
      if (this.projectOptions.configureWebpack) {
        this.webpackRawConfigFns.push(this.projectOptions.configureWebpack)
      }
    }

    if (isPromise(userOptions)) {
      return userOptions.then(loadedCallback)
    } else {
      return loadedCallback(userOptions)
    }
  }

init函数做了加载环境,用户的配置(vue.config.js) ,应用插件,整合项目的配置文件到webpack配置中一些事。 这就是为什么配置vue.config.js会起作用。

然后项目就启动了,至于怎么启动的这个fn函数后面再查,接下来看看重点,启动后项目资源结构。

浏览器的资源栏对应的是什么

使用 Webpack 启动 Vue 项目并在 Google Chrome 的开发者工具中查看源码时,顶层的目录(top directory),图片下三个子目录分别是:

1. localhost:8080 目录

localhost:8080 通常是本地开发服务器的地址。在开发过程中,Webpack Dev Server 或其他本地服务器会在这个地址上运行的应用。这个目录在开发者工具中显示,是为了能够方便地查看和调试运行在本地服务器上的代码。实际上,这个目录并不存在于文件系统中,而是开发者工具根据当前访问的URL动态生成的。

2. 项目名称目录(如 fof

项目名称目录(例如fof)通常代表了项目的根目录。这个目录包含了项目的所有源代码文件,如Vue组件、JavaScript文件、CSS文件等。在开发者工具中,这个目录会以文件系统的形式展示,能够方便地查看和编辑项目中的文件。这个目录实际上存在于文件系统中,是开发者工具直接读取和展示项目文件的结果。

3. webpack-internal 目录

webpack-internal 目录包含了由Webpack内部生成的代码和资源。Webpack在打包过程中,会生成一些用于内部管理的代码和模块,例如模块映射、热更新(Hot Module Replacement)代码等。这些代码和模块对于Webpack的正常运行至关重要。在开发者工具中,这些代码会被归类到webpack-internal目录下,以便能够查看和调试。这个目录并不存在于的文件系统中,而是由开发者工具根据Webpack打包生成的代码动态生成的。

下一个问题:

打印出来的导入的App。这些个属性我虽然知道是怎么出来的

js 复制代码
import { render } from "./App.vue?vue&type=template&id=7ba5bd90"
import script from "./App.vue?vue&type=script&setup=true&lang=js"
export * from "./App.vue?vue&type=script&setup=true&lang=js"

import exportComponent from "../node_modules/vue-loader/dist/exportHelper.js"
const __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__file',"src/App.vue"]])
/* hot reload */
if (module.hot) {
  __exports__.__hmrId = "7ba5bd90"
  const api = __VUE_HMR_RUNTIME__
  module.hot.accept()
  if (!api.createRecord('7ba5bd90', __exports__)) {
    api.reload('7ba5bd90', __exports__)
  }
  
  module.hot.accept("./App.vue?vue&type=template&id=7ba5bd90", () => {
    api.rerender('7ba5bd90', render)
  })

}


export default __exports__

这个文件是App.vue,__exports__就是上图返回的对象,那么这个对象是怎么出来的呢。

const __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__file',"src/App.vue"]])

script对应的是setup(),render对应的是render(),但是我们看到import过来的地址文件, "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&setup=true&lang=js" 这些个文件却发现在babel中

而且每个.vue分别有type=script和type=template各一个,对应上面对象的setup()和render()函数,所以可以推断的是.vue文件的的template标签、script标签、style标签被分开了,现在目前知道的是template标签变成了render()渲染函数,script标签变成了setup()函数,那么style标签呢到哪儿去了?遗留问题 后面再查查。还有一个问题为什么会出现在babal-loader/lib里?

相关推荐
也无晴也无风雨29 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤5 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui