{"id":21937428,"url":"https://github.com/packingjs/generator-packing","last_synced_at":"2026-04-16T12:33:56.422Z","repository":{"id":57248297,"uuid":"63658097","full_name":"packingjs/generator-packing","owner":"packingjs","description":null,"archived":false,"fork":false,"pushed_at":"2023-04-17T08:49:53.000Z","size":1142,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-28T17:13:45.257Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/packingjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-19T03:44:45.000Z","updated_at":"2020-10-20T12:26:16.000Z","dependencies_parsed_at":"2025-01-27T13:46:22.940Z","dependency_job_id":"b1ad8b72-6bde-4c21-98b3-e4e2f445bc87","html_url":"https://github.com/packingjs/generator-packing","commit_stats":null,"previous_names":[],"tags_count":51,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/packingjs%2Fgenerator-packing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/packingjs%2Fgenerator-packing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/packingjs%2Fgenerator-packing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/packingjs%2Fgenerator-packing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/packingjs","download_url":"https://codeload.github.com/packingjs/generator-packing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244967642,"owners_count":20539991,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T01:19:44.973Z","updated_at":"2026-04-16T12:33:51.389Z","avatar_url":"https://github.com/packingjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# generator-packing\n\n一个快速生成 [Packing](https://packingjs.github.io/) 工程的手脚架工具。\n\n## 特点\n* 不依赖 host 文件，根据环境自动切换资源路径\n* 节约开发服务器，多分支开发部署到同一台服务器不会相互覆盖\n* 提供资源包体积分析报告\n* 自动生成模版文件\n\n## 使用步骤\n1. 全局安装`yo`和`generator-packing`\n  ```\n  npm install -g yo generator-packing\n  ```\n\n1. 在目标目录运行以下命令，该命令会帮助你完成工程初始化和依赖包安装\n  ```\n  yo packing\n  ```\n\n1. 启动开发模式\n  ```\n  npm run serve\n  ```\n  如果上面的代码运行不报错的话，就可以在 `http://localhost:8081` 预览网站了\n\n## 命令\n* **npm start**: 启动开发模式\n* **npm start:dist**: 预览编译后的工程\n* **npm build**: 本地编译\n* **npm build:dev**: 编译到开发机\n* **npm build:beta**: 编译到测试机\n* **npm build:prod**: 编译到线上机\n* **npm serve**: `npm start` 的别名\n* **npm serve:dist**: `npm start:dist` 的别名\n* **npm lint**: 代码检查\n\n## 目录结构\n\n```\n.\n├── /assets/      # 图片字体等资源\n│   ├── /images/  # 图片（示例）\n│   └── /fonts/   # 字体（示例）\n├── /config/\n│   ├── /packing.js             # packing配置\n│   ├── /webpack.build.babel.js # webpack编译配置\n│   ├── /webpack.dll.babel.js   # webpack DllPlugin编译配置\n│   └── /webpack.serve.babel.js # webpack开发环境配置\n├── /mock/\n│   ├── /api              # 异步请求接口模拟数据存放目录\n│   │   └── /now.js       # /api/now接口模拟数据（示例）\n│   └── /pages            # 初始化网页的模拟数据\n│       ├── /__global.js  # 所有页面初始化通用的数据\n│       ├── /index.js     # /index页面初始化的数据（示例）\n│       └── /about.js     # /about页面初始化的数据（示例）\n├── /profiles/\n│   ├── /beta.env         # 测试环境profile文件\n│   ├── /development.env  # 开发环境profile文件\n│   ├── /local.env        # 本地环境profile文件\n│   └── /production.env   # 线上环境profile文件\n├── /src/                           \n│   ├── /common/                    # 公共代码\n│   ├── /pages/                     # DllPlugin插件编译配置\n│   │   ├── /index/                 # 首页的资源文件（示例）\n│   │   │   ├── /entry.js           # entry pointer\n│   │   │   └── /entry.settings.js  # 自动生成模版使用的配置文件（可选）\n│   │   └── /about/                 # about页的资源文件（示例）\n│   │   │   ├── /entry.js           # entry pointer\n│   │   │   └── /entry.settings.js  # 自动生成模版使用的配置文件可选）\n│   └── /templates                  # 模版文件\n│       ├── /layout/                # （pug用的）模版布局文件\n│       └── /pages/                 # 用来生成页面的模版文件\n├── /util/            # util\n├── .babelrc          # babel配置\n├── .env              # NODE_ENV环境变量配置，该文件不要提交到git仓库\n├── .eslintrc.js      # eslint配置\n├── build.sh          # jenkins发布调用的脚本\n├── pom.xml           # 前后端关联maven配置\n├── postcss.config.js # postcss配置\n└── README.md\n```\n\n## packing.js 配置说明\n```js\n{\n  /**\n   * 工程使用的编译平台\n   * 目前支持\n   * - portal\n   * - qdr\n   * @type {string}\n   */\n  ci: 'portal',\n\n  /**\n   * 本地访问的域名\n   * 如果需要使用 `qunar.com` 的 cookie，需要改成类似 `my.qunar.com` 这种\n   * @type {string}\n   */\n  localhost: 'localhost',\n\n  /**\n   * webserver 端口\n   */\n  port: {\n    /**\n     * 开发环境 webserver 端口\n     * @type {number}\n     */\n    dev: 8081,\n\n    /**\n     * 预览编译结果时 webserver 端口\n     * @type {number}\n     */\n    dist: 8080\n  },\n\n  /**\n   * 文件路径配置\n   * 所有目录都使用相对于项目根目录的相对目录格式\n   */\n  path: {\n    /** 源文件相关路径 */\n    src: {\n      /**\n       * 源文件根目录\n       * @type {string}\n       */\n      root: 'src',\n\n      /**\n       * 模版文件路径\n       * 相对于 `src.root` 的相对地址\n       * 若不区分布局文件和网页文件，请直接传入字符串\n       * @type {(string|object)}\n       */\n      templates: {\n        layout: 'templates/layout',\n        pages: 'templates/pages'\n      }\n    },\n\n    /** 编译输出文件相关路径 */\n    dist: {\n      /**\n       * webpack 编译产物输出目录\n       * 即 `webpack.config.output.path` 参数\n       * portal dev 发布时要求输出到 `dev` 目录\n       * qdr dev 发布时要求输出到 `prd` 目录\n       * @type {string}\n       */\n      root: process.env.NODE_ENV === 'development' ? 'dev' : 'prd',\n\n      /**\n       * 模版文件路径\n       * 相对于 `dist.root` 的相对地址\n       * 若不区分布局文件和网页文件，请直接传入字符串\n       * @type {(string|object)}\n       */\n      templates: {\n        layout: 'templates/layout',\n        pages: 'templates/pages'\n      },\n\n      /**\n       * JavaScript 输出目录\n       * @type {string}\n       */\n      js: 'js',\n\n      /**\n       * CSS 输出目录\n       * @type {string}\n       */\n      css: 'css'\n    },\n\n    /**\n     * 页面初始化 mock 数据文件存放目录\n     * @type {string}\n     */\n    mockPages: 'mock/pages',\n\n    /**\n     * dllPlugin 编译输出物临时存放目录\n     * @type {string}\n     */\n    tmpDll: '.tmp/dll',\n\n    /**\n     * 打包入口文件\n     * @type {(string|object|function)}\n     * @example\n     * // string\n     * entries: './src/entries/index.js'\n     * @example\n     * // object\n     * entries: {\n     *   index: './src/entries/index.js',\n     *   abc: './src/entries/abc.less'\n     * }\n     * @example\n     * // function\n     * entries: () =\u003e {}\n     */\n    entries: () =\u003e {\n      const entryFileName = 'entry.js';\n      const entryPath = 'src/pages';\n      const entryPattern = `**/${entryFileName}`;\n      const cwd = path.resolve(context, entryPath);\n      const config = {};\n      packingGlob(entryPattern, { cwd }).forEach((page) =\u003e {\n        const key = page.replace(`/${entryFileName}`, '');\n        config[key] = path.join(cwd, page);\n      });\n      return config;\n    }\n  },\n\n  /** 模版配置 */\n  template: {\n    /**\n     * 是否启用 packing template\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * packing template 选项\n     * @type {object}\n     */\n    options: {\n      /**\n       * 模版引擎类型\n       * 目前支持\n       * - html\n       * - pug\n       * - ejs\n       * - handlebars\n       * - smarty\n       * - velocity\n       * @type {string}\n       */\n      engine: 'pug',\n\n      /**\n       * 模版文件扩展名\n       * @type {string}\n       */\n      extension: '.pug',\n\n      /**\n       * 是否根据 `entry pointer` 自动生成网页文件\n       * 如需兼容 packing@\u003c3.0.0 的工程，该值设置为 false\n       * @type {bool}\n       */\n      autoGeneration: true,\n\n      /**\n       * 是否往模版中注入 assets\n       * @type {bool}\n       */\n      inject: true,\n\n      /**\n       * JavaScript Chunk 注入的位置\n       * - 'head': 在\u003c/head\u003e前注入\n       * - 'body': 在\u003c/body\u003e前注入\n       * @type {'head'|'body'}\n       */\n      scriptInjectPosition: 'body',\n\n      /**\n       * 是否往模版中注入 PWA manifest.json\n       * @type {bool}\n       */\n      injectManifest: false,\n\n      /**\n       * `manifest.json` 输出位置\n       * @type {string}\n       */\n      manifest: 'manifest.json',\n\n      /**\n       * 母模版位置\n       * @type {string}\n       */\n      master: 'src/templates/pages/default.pug',\n\n      /**\n       * 输出网页使用的字符编码\n       * @type {string}\n       */\n      charset: 'UTF-8',\n\n      /**\n       * 输出网页使用的标题\n       * @type {string}\n       */\n      title: '',\n\n      /**\n       * 输出网页使用的 favicon 图标\n       * - false: 不使用 favicon 图标\n       * - 非空字符串: favicon 图标的位置\n       * @type {(bool|string)}\n       */\n      favicon: false,\n\n      /**\n       * 输出网页使用的关键字\n       * @type {(bool|string)}\n       */\n      keywords: false,\n\n      /**\n       * 输出网页使用的描述\n       * @type {(bool|string)}\n       */\n      description: false,\n\n      /**\n       * 网页文件中需要在编译时替换为 _hash 的标签属性列表\n       * 格式为 tag:attribute\n       * 如果想对所有标签的某个属性替换，请使用 * 代替 tag\n       * 如所有标签的 src 属性都需要替换，则使用 *:src\n       * @example ['*:src', 'link:href']\n       * @type {array}\n       */\n      attrs: ['img:src', 'link:href'],\n\n      /**\n       * 模版中命中的静态文件编译输出的文件名\n       * @type {string}\n       */\n      path: '[path][name]_[hash:8].[ext]'\n    }\n\n  },\n\n  /** HRM 配置 */\n  hot: {\n    /**\n     * 是否启用热模块替换\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * HRM 选项\n     * @type {object}\n     * @see {@link https://github.com/webpack-contrib/webpack-hot-middleware|webpack-hot-middleware}\n     */\n    options: {}\n  },\n\n  /** 长效缓存配置 */\n  longTermCaching: {\n    /**\n     * 是否启用编译时文件 hash 重命名\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * 缓存选项\n     * @type {object}\n     */\n    options: {\n      /**\n       * 文件名与 hash 连接使用的字符串\n       * @type {string}\n       */\n      delimiter: '_',\n\n      /**\n       * hash 长度\n       * @type {number}\n       */\n      fileHashLength: 8\n    }\n  },\n\n  /** 压缩代码配置 */\n  minimize: {\n    /**\n     * 是否压缩代码\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * uglifyjs plugin 配置\n     * @type {object}\n     */\n    options: {\n      // sourceMap: true,\n      uglifyOptions: {\n        output: {\n          // beautify: true,\n          // 删除注释代码\n          comments: false\n        }\n      }\n    }\n  },\n\n  /**\n   * `css-loader` 配置项\n   * @type {object}\n   * @see {@link https://github.com/webpack-contrib/css-loader|css-loader}\n   */\n  cssLoader: {\n    /**\n     * 在 css loader 之前应用的 loader 数量\n     * @type {number}\n     */\n    importLoaders: 2,\n    /**\n     * 是否启用 `CSS Modules`\n     * @type {bool}\n     */\n    modules: false,\n\n    /**\n     * 自定义css-modules类标识命名规则\n     * @type {string}\n     */\n    localIdentName: '[path][name]__[local]--[hash:base64:5]'\n  },\n\n  /** stylelint 配置 */\n  stylelint: {\n    /**\n     * 是否启用 `stylelint`\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * `stylelint` 配置项\n     * @type {object}\n     * @see {@link https://stylelint.io/user-guide/node-api/#options|stylelint options}\n     */\n    options: {\n      files: ['**/*.css', '**/*.less', '**/*.s?(a|c)ss']\n    }\n  },\n\n  /** eslint 配置 */\n  eslint: {\n    /**\n     * 是否启用 `eslint`\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * `eslint` 配置项\n     * @type {object}\n     * @see {@link https://github.com/webpack-contrib/eslint-loader|eslint options}\n     */\n    options: {\n    }\n  },\n\n  /**\n   * runtimeChunk 配置\n   * @see https://webpack.js.org/plugins/split-chunks-plugin/\n   */\n  runtimeChunk: {\n    /**\n     * 是否启用 runtimeChunk\n     * @type {bool}\n     */\n    enabled: false,\n\n    /**\n     * runtimeChunk 输出的文件名\n     * @type {string}\n     */\n    name: 'runtime'\n  },\n\n  /**\n   * commonChunks 配置\n   * 可以配置多个 common 包，配置的包名称会转换为正则表达式\n   * 该配置分别在以下过程中被调用：\n   * - 在 `packing serve` 任务中被 `DllPlugin` 调用\n   * - 在 `packing build` 任务中被 `SplitChunkPlugin` 调用\n   * 注意，如果配置了commonChunks，所有网页模版需要引用公共包文件\n   * 否则会报错\n   * \u003cscript src=\"/vendor.js\"\u003e\u003c/script\u003e\n   * @type {object}\n   * @see https://webpack.js.org/plugins/split-chunks-plugin/\n   */\n  commonChunks: {\n    // vendor: [\n    //   'react',\n    //   'react-dom'\n    //   'packing-ajax'\n    // ]\n  },\n\n  /**\n   * webpack-visualizer-plugin 配置\n   * @see https://github.com/chrisbateman/webpack-visualizer\n   */\n  visualizer: {\n    /**\n     * 是否启用 webpack-visualizer-plugin\n     * @type {bool}\n     */\n    enabled: true,\n\n    /**\n     * `visualizer` 配置项\n     * @type {object}\n     */\n    options: {\n      /**\n       * 是否在浏览器中打开 visualizer 报表网页\n       * 和 `packing build -o` 效果一样\n       * @type {object}\n       */\n      open: process.env.npm_lifecycle_event === 'build'\n    }\n  },\n\n  /** graphql 配置 */\n  graphql: {\n    /**\n     * 是否使用 `GraphQL-mock-server`\n     * @type {bool}\n     */\n    enabled: false,\n\n    options: {\n      /**\n       * GraphQL 地址\n       * @type {string}\n       */\n      graphqlEndpoint: '/graphql',\n\n      /**\n       * GraphiQL 地址\n       * @type {string}\n       */\n      graphiqlEndpoint: '/graphiql'\n    }\n  },\n\n  /**\n   * 静态资源类型\n   * @type {array}\n   */\n  assetExtensions: [\n    'jpg',\n    'jpeg',\n    'png',\n    'gif',\n    'mp3',\n    'ttf',\n    'woff',\n    'woff2',\n    'eot',\n    'svg'\n  ],\n\n  /**\n   * URL转发路由规则配置\n   * `require!` 表示使用本地 mock 文件\n   * @type {object}\n   */\n  rewriteRules: {\n    /** API转发 */\n    '^/api/(.*)': 'require!/mock/api/$1.js'\n  }\n};\n```\n\n\n## 迁移到 packing 3\n### 修改点\n* 升级依赖包\n  * packing@latest\n  * packing-template-pug@^2.0.4\n  * packing-urlrewrite@^0.1.8\n* 用 `file-loader` 代替 `url-loader` 加载静态文件\n* 使用 `dotenv` 加载 `process.env` 环境变量\n* 将 `packing-template` 合并到 `packing` 工程，方便开发调试\n* 调整 `packing.path` 结构\n    - `path.dll` 更名为 `path.tmpDll`\n    - 删除 `assetsDist` `templatesDist` `templatesPagesDist`\n    - 删除 `packing.path.assets` 配置，如果希望直接 `import` `path.assets` 下的文件请使用 `webpack.resolve.alias` 设置\n      ```js\n      webpackConfig.resolve.alias = {\n        assets: 'assets'\n      };\n      ```\n    - 分为 `src` `dist` 两类，每种目录均使用 `root` 的相对目录\n    - 简化 `templates` 目录设置\n      - {string}:\n      - {object}\n        - layout:\n        - pages:\n    - `mockPageInit` 更名为 `mockPages`\n\n* `path.templates` 结构调整\n    - 兼容字符串类型参数\n    - 允许传入包含 `layout` `pages` 的对象参数\n\n* 默认模版类型改为 `pug`\n    - `templateEngine` 默认值由 `html` 改为 `pug`\n    - `templateExtension` 默认值由 `.html` 改为 `.pug`\n\n* `src/profiles` --\u003e `profiles`\n    - 位置变化：该目录无需编译，移动到 `src` 目录外\n    - 格式变化：使用 `key=value` 的方式描述，每行一个配置\n\n* 编译输出目录由 `prd/assets/` 变更为 `prd/`\n* `config/packing.js` 增加了更多的配置参数\n* 增加 `stylelint` 功能\n* 增加包体积分析报表\n* 使用 `SplitChunkPlugin` 代替 `CommonChunkPlugin`，配置 vendor 时支持正则\n\n### 迁移步骤\n1. 升级依赖\n  ```\n  npm i --registry https://registry.npm.taobao.org packing@latest packing-template-pug@^2.0.4 packing-urlrewrite@^0.1.8 webpack-dev-middleware@^3.1.2 webpack-hot-middleware@^2.22.0\n  ```\n2. 创建 `.env`\n  ```\n  echo NODE_ENV=local \u003e .env\n  ```\n3. 移动并修改 `src/profiles` -\u003e `profiles`\n  ```\n  mv src/profiles profiles\n  ```\n4. 修改配置 `config/packing.js`\n\n5. 创建 ${entrypoint}.setttings.js，为网页设置标题\n  ```js\n  export default {\n    title: '网页标题'\n  };\n  ```\n\n### 新手入门\n\n#### 如何新增一个页面\n假设新增页面的路由为 `/login`，只需要新增入口文件  `src/pages/login/entry.js` 即可：\n\n```js\n// src/pages/login/entry.js\ndocument.write('login');\n```\n\n使用 `http://localhost:8081/login` 查看页面效果。\n\n#### 如何使用不同的母模版\n所有网页默认都是通过模版自动生成出来的，默认母模版的位置为 `src/templates/pages/default.pug`。\n\n可以使用与 `${entrypoint}.js` 同级目录的 `${entrypoint}.settings.js` 来控制该 ${entrypoint} 使用母模版。\n```js\n// src/pages/login/entry.settings.js\nexport default {\n  master: 'src/templates/layout/other.pug'\n};\n```\n\n#### 如何控制网页标题\n和自定义母模版的方式一样，可以使用 `${entrypoint}.settings.js` 来控制网页标题，类似的可控制的参数还有 `keywords` 和 `description`。\n\n```js\n// src/pages/login/entry.settings.js\nexport default {\n  title: '登录',\n  // keywords: '登录 注册',\n  // description: '这是登录页'\n};\n```\n\n#### 如何自定义入口文件匹配规则\n除了定义入口文件外，Packing对目录结构没有要求，packing默认的入口配置是获取 `src/pages/**/entry.js`，你可以根据实际情况修改 `config/packing.js` 配置来达到自己需要的结构方式。\n\n下面的配置将修改入口文件规则为 `src/entries/**/*.js`:\n\n```js\n// config/packing.js\nimport path from 'path';\nimport packingGlob from 'packing-glob';\n\nexport default (packing) =\u003e {\n  const p = packing;\n\n  //...\n\n  p.path.entries = () =\u003e {\n    const entryPath = 'src/entries';\n    const entryPattern = '**/*.js';\n    const cwd = path.resolve(context, entryPath);\n    const config = {};\n    packingGlob(entryPattern, { cwd }).forEach((page) =\u003e {\n      const ext = path.extname(page).toLowerCase();\n      const key = page.replace(ext, '');\n      config[key] = path.join(cwd, page);\n    });\n    return config;    \n  };\n\n  //...\n\n  return p;\n};\n```\n\n#### 如何模拟异步请求的返回结果\n请查看[数据模拟文档](https://github.com/packingjs/generator-packing/blob/master/generators/app/templates/mock/README.md)\n\n#### 如何模拟页面初始化数据\n请查看[数据模拟文档](https://github.com/packingjs/generator-packing/blob/master/generators/app/templates/mock/README.md)\n\n#### 如何自定义页面的 URL 规则\n`Packing` 默认会为每一个入口增加一个路由 `/${entrypoint}`。在实际项目中，可能存在线上路由和入口并不是对应关系，这时需要手动配置 `packing` 路由规则，以确保本地环境和线上环境更一致。\n\n\u003e假设需要把网站的登录页设置为网站首页\n\n可以通过修改 `config/packing.js` 来达到这一目的。\n\n```js\n// config/packing.js\nexport default (packing) =\u003e {\n  const p = packing;\n\n  //...\n\n  p.rewriteRules = {\n    //...\n\n    '^/$': '/login'\n\n    //...\n  };\n\n  //...\n\n  return p;\n};\n```\n\n#### 如何修改packing中定义的webpack配置\n可以通过修改 `config/webpack.*.babel.js` 来修改 `webpack` 配置\n\n```js\nexport default (webpackConfig) =\u003e {\n  const config = webpackConfig;\n  // 删除 extract-text-plugin\n  config.plugins = config.plugins.filter(\n    plugin =\u003e plugin.constructor.name !== 'ExtractTextPlugin'\n  );\n\n  // 新增 html-webpack-plugin\n  config.plugins.push(new HtmlWebpackPlugin());\n  return config;\n};\n\n```\n\n#### 在jenkins编译时提示找不到某些依赖包，但本地编译正常\n本地开发时用的npm安装命令是 `npm install` ，它会`devDependencies`和`dependencies`包含的所有包，为了减少不必要的包安装、提高安装速度，在编译服务器上用的npm安装命令是 `npm install --production`，它只会安装`dependencies`下的包。出现这种情况是因为包的位置摆放错误，你需要把在编译服务器上提示找不到的这些包从`devDependencies`移动到`dependencies`下。\n\n## 发布\n### QRD\n* 使用 `node` 编译方式：\n  ```\n  fe.xxx.build_method=node\n  ```\n* 使用 `sfile` 编译方式：\n  ```\n  fe.xxx.build_method=sfile\n  # 将下行的 xxx 换成 \u003cdevelopment|beta|prod\u003e 其中一个\n  fe.xxx.build_command: sh ./build.sh xxx\n  ```\n\n相比较 `sfile` 而言，`node` 会多做两件事：\n1. 安装依赖包\n2. 根据环境自动调用以下三个命令中的一个\n  * npm run build:**development**\n  * npm run build:**beta**\n  * npm run build:**prod**\n\n从上面的比较可以看出，使用 `node` 比较简单，使用 `sfile` 灵活性更强。\n`node` 使用的是公司内部npm源，稳定性差，有些包无论如何都下载失败，另外该方式需要 `CM` 来支持，推荐大家使用 `sfile`。\n\n### portal\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpackingjs%2Fgenerator-packing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpackingjs%2Fgenerator-packing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpackingjs%2Fgenerator-packing/lists"}