text: // @ts-check
  import path from 'path'
  import ts from 'rollup-plugin-typescript2'
  import replace from '@rollup/plugin-replace'
  import json from '@rollup/plugin-json'
  
  //package 里面的每个包都可以独立运行
  if (!process.env.TARGET) {
    throw new Error('TARGET package must be specified via --environment flag.')
  }
  
  const masterVersion = require('./package.json').version //版本
  const packagesDir = path.resolve(__dirname, 'packages') //packages包目录
  
  // process.env.TARGET 确定命令行 比如yarn dev (vue)有没有带指定运行的包  没有默认用vue
  const packageDir = path.resolve(packagesDir, process.env.TARGET) //具体到包内
  
  const resolve = p => path.resolve(packageDir, p)
  const pkg = require(resolve(`package.json`)) //package某个包里面的package.json
  const packageOptions = pkg.buildOptions || {} //build配置
  //path.basename() 方法返回 path 的最后一部分，类似于 Unix basename 命令  path.basename('user/vue/hello/wotd/end') ===> 'end'
  const name = packageOptions.filename || path.basename(packageDir)
  
  // ensure TS checks only once for each build
  let hasTSChecked = false
  
  //设置rollup 输出格式
  const outputConfigs = {
    'esm-bundler': {
      file: resolve(`dist/${name}.esm-bundler.js`),
      format: `es`
    },
    'esm-browser': {
      file: resolve(`dist/${name}.esm-browser.js`),
      format: `es`
    },
    cjs: {
      file: resolve(`dist/${name}.cjs.js`),
      format: `cjs`
    },
    global: {
      file: resolve(`dist/${name}.global.js`),
      format: `iife`
    },
  
    // runtime-only builds, for main "vue" package only
    'esm-bundler-runtime': {
      file: resolve(`dist/${name}.runtime.esm-bundler.js`),
      format: `es`
    },
    'esm-browser-runtime': {
      file: resolve(`dist/${name}.runtime.esm-browser.js`),
      format: 'es'
    },
    'global-runtime': {
      file: resolve(`dist/${name}.runtime.global.js`),
      format: 'iife'
    }
  }
  
  const defaultFormats = ['esm-bundler', 'cjs']
  const inlineFormats = process.env.FORMATS && process.env.FORMATS.split(',') //命令行inline 的formats
  const packageFormats = inlineFormats || packageOptions.formats || defaultFormats
  //判断是否只是打包  每个包的打包配置
  const packageConfigs = process.env.PROD_ONLY
    ? []
    : packageFormats.map(format => createConfig(format, outputConfigs[format]))
  
  if (process.env.NODE_ENV === 'production') {
    packageFormats.forEach(format => {
      if (packageOptions.prod === false) {
        return
      }
      if (format === 'cjs') {
        packageConfigs.push(createProductionConfig(format))
      }
      if (/^(global|esm-browser)(-runtime)?/.test(format)) {
        packageConfigs.push(createMinifiedConfig(format))
      }
    })
  }
  
  export default packageConfigs
  
  function createConfig(format, output, plugins = []) {
    if (!output) {
      console.log(require('chalk').yellow(`invalid format: "${format}"`)) //没有output 提示format无效 退出进程
      process.exit(1)
    }
  
    //命令写在前面可以取到值 __DEV__=false node rollup/path.js  process.env.__DEV__  = false
  
    const isProductionBuild =
      process.env.__DEV__ === 'false' || /\.prod\.js$/.test(output.file) //是否是生产环境打包
    const isBundlerESMBuild = /esm-bundler/.test(format)
    const isBrowserESMBuild = /esm-browser/.test(format)
    const isNodeBuild = format === 'cjs'
    const isGlobalBuild = /global/.test(format)
    const isCompatPackage = pkg.name === '@vue/compat' //vue2兼容包 迁移构建
    const isCompatBuild = !!packageOptions.compat
  
    output.exports = isCompatPackage ? 'auto' : 'named'
    output.sourcemap = !!process.env.SOURCE_MAP
    output.externalLiveBindings = false //？？？设置为false 不会生成代码来支持外部导入的实时绑定，而是假设导出不会随着时间的推移而改变 代码回更优化
  
    if (isGlobalBuild) {
      output.name = packageOptions.name
    }
    //ts type 是否声明   hasTSChecked tsplugin 只处理一次
    const shouldEmitDeclarations =
      pkg.types && process.env.TYPES != null && !hasTSChecked
  
    const tsPlugin = ts({
      check: process.env.NODE_ENV === 'production' && !hasTSChecked,
      tsconfig: path.resolve(__dirname, 'tsconfig.json'),
      cacheRoot: path.resolve(__dirname, 'node_modules/.rts2_cache'),
      tsconfigOverride: {
        compilerOptions: {
          sourceMap: output.sourcemap,
          declaration: shouldEmitDeclarations,
          declarationMap: shouldEmitDeclarations
        },
        exclude: ['**/__tests__', 'test-dts']
      }
    })
    // we only need to check TS and generate declarations once for each build.
    // it also seems to run into weird issues when checking multiple times
    // during a single build.
    hasTSChecked = true
  
    let entryFile = /runtime$/.test(format) ? `src/runtime.ts` : `src/index.ts`
  
    // the compat build needs both default AND named exports. This will cause
    // Rollup to complain for non-ESM targets, so we use separate entries for
    // esm vs. non-esm builds.
    if (isCompatPackage && (isBrowserESMBuild || isBundlerESMBuild)) {
      entryFile = /runtime$/.test(format)
        ? `src/esm-runtime.ts`
        : `src/esm-index.ts`
    }
  
    let external = []
  
    if (isGlobalBuild || isBrowserESMBuild || isCompatPackage) {
      if (!packageOptions.enableNonBrowserBranches) {
        // normal browser builds - non-browser only imports are tree-shaken,
        // they are only listed here to suppress warnings.
        external = ['source-map', '@babel/parser', 'estree-walker']
      }
    } else {
      // Node / esm-bundler builds.
      // externalize all deps unless it's the compat build.
      external = [
        ...Object.keys(pkg.dependencies || {}),
        ...Object.keys(pkg.peerDependencies || {}),
        ...['path', 'url', 'stream'] // for @vue/compiler-sfc / server-renderer
      ]
    }
  
    // the browser builds of @vue/compiler-sfc requires postcss to be available
    // as a global (e.g. http://wzrd.in/standalone/postcss)
    output.globals = {
      postcss: 'postcss'
    }
  
    const nodePlugins =
      packageOptions.enableNonBrowserBranches && format !== 'cjs'
        ? [
            // @ts-ignore
            require('@rollup/plugin-commonjs')({
              sourceMap: false
            }),
            // @ts-ignore
            require('rollup-plugin-polyfill-node')(),
            require('@rollup/plugin-node-resolve').nodeResolve() //整合外部模组程式码，将我们编写的原始码与依赖的第三方库进行合并，使用者在引用我们库的时候，就不需要手动去下载这个库所有的依赖
          ]
        : []
  
    return {
      input: resolve(entryFile),
      // Global and Browser ESM builds inlines everything so that they can be
      // used alone.
      external,
      plugins: [
        json({
          namedExports: false
        }),
        tsPlugin,
        createReplacePlugin(
          isProductionBuild,
          isBundlerESMBuild,
          isBrowserESMBuild,
          // isBrowserBuild?
          (isGlobalBuild || isBrowserESMBuild || isBundlerESMBuild) &&
            !packageOptions.enableNonBrowserBranches,
          isGlobalBuild,
          isNodeBuild,
          isCompatBuild
        ),
        ...nodePlugins,
        ...plugins
      ],
      output,
      onwarn: (msg, warn) => {
        if (!/Circular/.test(msg)) {
          warn(msg)
        }
      },
      treeshake: {
        moduleSideEffects: false
      }
    }
  }
  
  //类比Webpack 的DefinePlugin
  function createReplacePlugin(
    isProduction,
    isBundlerESMBuild,
    isBrowserESMBuild,
    isBrowserBuild,
    isGlobalBuild,
    isNodeBuild,
    isCompatBuild
  ) {
    const replacements = {
      __COMMIT__: `"${process.env.COMMIT}"`,
      __VERSION__: `"${masterVersion}"`,
      __DEV__: isBundlerESMBuild
        ? // preserve to be handled by bundlers
          `(process.env.NODE_ENV !== 'production')`
        : // hard coded dev/prod builds
          !isProduction,
      // this is only used during Vue's internal tests
      __TEST__: false,
      // If the build is expected to run directly in the browser (global / esm builds)
      __BROWSER__: isBrowserBuild,
      __GLOBAL__: isGlobalBuild,
      __ESM_BUNDLER__: isBundlerESMBuild,
      __ESM_BROWSER__: isBrowserESMBuild,
      // is targeting Node (SSR)?
      __NODE_JS__: isNodeBuild,
  
      // for compiler-sfc browser build inlined deps
      ...(isBrowserESMBuild
        ? {
            'process.env': '({})',
            'process.platform': '""',
            'process.stdout': 'null'
          }
        : {}),
  
      // 2.x compat build
      __COMPAT__: isCompatBuild,
  
      // feature flags
      __FEATURE_SUSPENSE__: true,
      __FEATURE_OPTIONS_API__: isBundlerESMBuild ? `__VUE_OPTIONS_API__` : true,
      __FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild
        ? `__VUE_PROD_DEVTOOLS__`
        : false,
      ...(isProduction && isBrowserBuild
        ? {
            'context.onError(': `/*#__PURE__*/ context.onError(`,
            'emitError(': `/*#__PURE__*/ emitError(`,
            'createCompilerError(': `/*#__PURE__*/ createCompilerError(`,
            'createDOMCompilerError(': `/*#__PURE__*/ createDOMCompilerError(`
          }
        : {})
    }
    // allow inline overrides like
    //__RUNTIME_COMPILE__=true yarn build runtime-core
    Object.keys(replacements).forEach(key => {
      if (key in process.env) {
        replacements[key] = process.env[key]
      }
    })
    return replace({
      // @ts-ignore
      values: replacements,
      preventAssignment: true //如果是赋值的时候拒绝替换
    })
  }
  
  function createProductionConfig(format) {
    return createConfig(format, {
      file: resolve(`dist/${name}.${format}.prod.js`),
      format: outputConfigs[format].format
    })
  }
  
  function createMinifiedConfig(format) {
    const { terser } = require('rollup-plugin-terser')
    return createConfig(
      format,
      {
        file: outputConfigs[format].file.replace(/\.js$/, '.prod.js'),
        format: outputConfigs[format].format
      },
      [
        terser({
          module: /^esm/.test(format),
          compress: {
            ecma: 2015,
            pure_getters: true
          },
          safari10: true
        })
      ]
    )
  }
  