{"_id":"9fstock-vue-cli","_rev":"1-cc8a5d6afab85efa73f0146c41fdd144","name":"9fstock-vue-cli","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"9fstock-vue-cli","version":"1.0.0","author":{"name":"KyleWang"},"email":"417940197@qq.com","license":"MIT","scripts":{"dev":"vue-cli-service serve","build":"vue-cli-service build","lint":"vue-cli-service lint","precommit":"lint-staged"},"dependencies":{"@xunlei/vue-lazy-component":"^1.1.3","axios":"^0.18.0","cube-ui":"^1.10.11","fastclick":"^1.0.6","lodash":"^4.17.10","nprogress":"^0.2.0","qs":"^6.5.2","vue":"^2.5.17","vue-lazyload":"^1.2.6","vue-meta":"^1.5.3","vue-router":"^3.0.1","vuex":"^3.0.1","vuex-persistedstate":"^2.5.4"},"devDependencies":{"@vue/cli-plugin-babel":"^3.0.1","@vue/cli-plugin-eslint":"^3.0.1","@vue/cli-service":"^3.0.1","@vue/eslint-config-standard":"^3.0.1","axios-mock-adapter":"^1.15.0","babel-plugin-import":"^1.8.0","cssnano":"^4.0.5","cssnano-preset-advanced":"^4.0.0","happypack":"^5.0.0","husky":"^0.14.3","install":"^0.12.1","lint-staged":"^7.2.2","mockjs":"^1.0.1-beta3","npm":"^6.4.0","os":"^0.1.1","postcss-aspect-ratio-mini":"0.0.2","postcss-cssnext":"^3.1.0","postcss-import":"^12.0.0","postcss-px-to-viewport":"0.0.3","postcss-url":"^8.0.0","postcss-viewport-units":"^0.1.4","postcss-write-svg":"^3.0.1","stylus":"^0.54.5","stylus-loader":"^3.0.2","vconsole":"^3.2.0","vue-skeleton-webpack-plugin":"^1.1.18","vue-template-compiler":"^2.5.17","webpack-parallel-uglify-plugin":"^1.1.0","webpack-transform-modules-plugin":"^0.3.5"},"browserslist":["> 1%","last 2 versions","not ie <= 8"],"description":"---","_id":"9fstock-vue-cli@1.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.11.2","_npmUser":{"name":"kylewang1011","email":"417940197@qq.com"},"dist":{"integrity":"sha512-8kdfjqGnggCL/KXsbyNVq1euNEefJ5QkkRd9NfLW/hUJ6w3zYkK9HQH0QG6NskajhNSg+PmFHViOSgs/PY1GcA==","shasum":"c128b4fd4ea9dcfab917fbbfa512b37bcee1c005","tarball":"https://registry.npmjs.org/9fstock-vue-cli/-/9fstock-vue-cli-1.0.0.tgz","fileCount":64,"unpackedSize":599001,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbe/PaCRA9TVsSAnZWagAAJWwP/Rh9Y1LlS32JeeXzPs0k\nRLD0X3sEtlRmXrEWVlZejrH9KNVZeqwQnR1x1ej+4QuwH619RRqvzU3GuRQf\n0J23bHC6hnZMA+dTBXZcolpTQBFKsRD9FK+EzaZR/WfHZ4n/gjB59zVmp0le\n2wT3AYbtnG08rpU5nEHH1HwW0M0YTF+cis+PKnBBzp30FjOD+v+Z/j6E7YQV\nFGHFtF19u61P5466wu3Ll3cg1taPpYs7hhuD6XTp2ZF9hGYqlrYEUZIIrbsr\nrND8WEUttocsBVoyPHTAwhAQMWB/5GJDwLazFoSBsaq+x34btDwFCvWyWZpQ\nF177rGW03PdXM+96Jx3sh9Frp6jwaxnehpFiEISBHtNYTCZWuY6iI966IVOT\nPnF0Ny//5y4M9Nfk2OPYDNAuSvN7zPbuZmjCrtJdX5XtiGVu9ptZkQR3ql+N\n9sXm7Ili0CsuhbnYRfFTJbKmO51tw2Opq9FPP7dk2S1ESFREqsri3tNfn68e\nKzJsFwEvK4A52D+NM/lhOU3bYdW5oCbeEAUxe3kONVzyPt46lRpsnJHDfgkP\nh9t3sNkDAm1XguuvUcWGqsNIRl324BDn0pK+2bxJ5o5PAVOnA0w7sec+tN4I\n/w3Ze9/AfIY/LJQVH+z0YtJkO6IiIcMiEAewGm4SC3KnRObGdlrSEV8SIxfA\nrrPQ\r\n=iHYD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZDxPadTY7s8gTlXkpNDVIxFB3gPt/Sqn0R52954rZLwIhAKyLkrIM8VcVPa4iXANXwAkrDToWWvpE6bt5NXtpEvAL"}]},"maintainers":[{"name":"kylewang1011","email":"417940197@qq.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/9fstock-vue-cli_1.0.0_1534850009937_0.9075495886001077"},"_hasShrinkwrap":false}},"time":{"created":"2018-08-21T11:13:29.936Z","1.0.0":"2018-08-21T11:13:30.030Z","modified":"2022-04-04T10:25:22.159Z"},"maintainers":[{"name":"kylewang1011","email":"417940197@qq.com"}],"description":"---","author":{"name":"KyleWang"},"license":"MIT","readme":"#  玖富Vue-cli种子项目介绍\n\n---\n\n\n# 概览\n\n## Base\n+  **vue-cli3.0**\n\n## 注入插件\n+ **PostCss** => *支持px单位自动换算*\n+ **Stylus + Stylus-loader** => *支持Stylus语法糖*\n+ **VConsole** => *支持移动端调试控制台*\n+ **Lodash**  => *支持Js工具库*\n+ **NProgress** => *支持页面跳转顶部loading*\n+ **axios**  => *支持ajax数据请求和数据劫持*\n+ **mock.js** => *支持前端mock静态数据*\n+ **.editorConfig** => *支持编辑器统一代码格式化*\n+ **vue-meta**  => *支持SPA下单独设置页面title以及元信息*\n+ **husky + lint-staged**  => *支持Git钩子验证*\n+ **vue-lazyload**  => *支持图片懒加载*\n+ **vue-lazy-component**  => *支持模版懒加载，可做骨架屏优化*\n+ **vuex**  => *支持状态管理器*\n+ **vuex-persistedstate**  => *支持数据状态持久化*\n+ **vue-router** => *支持路由跳转管理*\n+ **vuex-router-sync** => *支持router的状态<path,query和params>存入vuex的state中*\n+ ...\n\n\n## UI库\n+ **cube-ui**  \n\n\n## Webpack 优化\n+ **Happypack**  => *多进程打包*\n+ **webpack-parallel-unglify-plugin** => *利用缓存快速压缩*\n+ ...\n\n\n## Feature\n+ **vue-i18n** => *多语言配置解决方案*\n+ **vue-class-component** => *以class的模式写Vue*\n+ **vuex-class-** => *装饰器语法写Vuex*\n+ **vue-property-decorator**  => *装饰器语法写钩子函数*\n+ **SSR**  => *支持服务端渲染*\n+ **Koa2/egg**  => *支持中间层*\n+ ...\n\n## 目录结构\n\n\n```\n├── package.json\t\t\t\t\t# npm包管理文件\n├── .postcssrc.js\t\t\t\t\t# postcss配置文件\n├── .eslintrc.js\t\t\t\t\t# eslint配置文件\n├── .editorconfig\t\t\t\t\t# editorconfig配置文件\n├── lint-staged.config.js\t\t\t# postcss配置文件\n├── babel.config.js\t\t\t\t# babel配置文件\n│── main.js                        # vue项目入口文件\n├── build\t\t \t\t\t\t\t# webpack配置\n│   ├── config.js\t\t\t\t\t# 参数配置文件\n│   ├── webpack.base.conf.js\t\t# 公共打包执行任务\n│   ├── webpack.dev.conf.js\t\t# 开发环境打包执行任务\n│   └── webpack.prod.conf.js\t\t# 生产环境打包执行任务\n├── mock\t\t\t\t\t\t\t\n│   ├── data\t\t\t\t\t\t# mock接口\n│   │   └── userinfo.js\n│   └── index.js\t\t\t\t\t# mock配置文件\n├── public\t\t\t\t\t\t\t\n│   ├── favicon.ico\n│   └── index.html\t\t\t\t\t# 入口页面\n├── src\n│   ├── App.vue\t\t\t\t\t# 入口组件\n│   ├── api\t\t\t\t\t\t# 接口请求处理\n│   │   ├── axios.js\t\t\t\t# axios请求拦截封装\n│   │   ├── config.js\t\t\t\t# axios请求参数配置\n│   │   └── index.js\t\t\t\t# 接口请求封装\n│   ├── common\t\t\t\t\t\t\n│   │   ├── image\n│   │   │   └── default.png\n│   │   └── stylus\n│   │       ├── base.styl\t\t\t# 公共全局样式\n│   │       ├── border.styl\t\t\t# 移动端1像素封装\n│   │       ├── index.styl\t\t\t# 入口文件\n│   │       ├── mixin.styl\t\t\t# 常用mixin<长期维护>\n│   │       ├── reset.styl\t\t\t# 接口请求封装\n│   │       └── variable.styl\t\t# 全局定义变量\n│   ├── components\t\t\t\t\n│   │   └── Skeleton.vue\t\t\t# 骨架屏组件\n│   ├── mock\t\t\t\t\t\t\n│   │   ├── data\t\t\t\t\t# mock接口\n│   │   │   └── users.js\n│   │   ├── index.js\t\t\t\t# mock出口方法\n│   │   └── mock.js\t\t\t\t# mock拦截处理\n│   ├── routers\t\t\t\t\t\t\n│   │   └── index.js\t\t\t\t# vue-router配置\n│   ├── store\t\t\t\t\t\t\n│   │   ├── modules\t\t\t\t# 功能模块\n│   │   ├── actions.js\t\t\t\t# 根级别的action\n│   │   ├── getters.js\t\t\t\t# 根级别的getters\n│   │   ├── index.js\t\t\t\t# store入口\n│   │   ├── mutation-types.js\t\t# 根级别的mutation-types\n│   │   ├── mutations.js\t\t\t# 根级别的mutations\n│   │   └── state.js\t\t\t\t# 根级别的state\n│   ├── utils\t\t\t\t\t\t# 工具方法库<长期维护>\n│   │   ├── array.js\n│   │   ├── cache.js\n│   │   ├── common.js\n│   │   ├── date.js\n│   │   ├── dom.js\n│   │   ├── is.js\n│   │   ├── object.js\n│   │   ├── storage.js\n│   │   ├── string.js\n│   │   └── url.js\n│   └── views\t\t\t\t\t\t# 业务页面组件\n│       ├── Home\n│       │   └── index.vue\n│       │   └── main.styl\n│       ├── Login\n│       │   └── index.vue\n│       │   └── main.styl\n│       ├── My\n│       │   └── index.vue\n│       │   └── main.styl\n└── vue.config.js\t\t\t\t    #vue全局配置文件\n```\n\n---\n\n# Base 脚手架\n> 主要基于vue-cli 3.0 版本做了一些提高团队生产力和开发效率的事情。推荐阅读[vue-cli官方文档](https://cli.vuejs.org/zh/)。\n---\n\n\n# 插件说明\n\n## PostCss\n\n> 这里有一个坑需要注意一下,踩了一坑，由于`postcss-px-to-viewport`并没有`exclude`配置项，所以会把`node_modules`里的ui库文件的css也包含进去进行转换，控制台会出现warning，所以需要做一些必要的处理。\n\n![warning](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/1.png?raw=true)\n\n```js\n\n// 此段代码在依赖包postcss-px-to-viewport/index.js里 大约第30行\n...\ncss.walkDecls(function (decl, i) {\n\nif (options.exclude) { // 添加对exclude选项的处理\n    if (Object.prototype.toString.call(options.exclude) !== '[object RegExp]') {\n      throw new Error('options.exclude should be RegExp!')\n    }\n    if (decl.source.input.file.match(options.exclude) !== null) return;\n}\n...\n\n```\n然后就在`.postcssrc`配置文件里添加\n\n```js\n...\n \"postcss-px-to-viewport\":{\n     ...\n    exclude: /(\\/|\\\\)(node_modules)(\\/|\\\\)/  // 忽略node_modules\n }\n```\n> 编译前\n\n![stylus](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/7.png?raw=true)\n\n> 编译后\n\n![css1](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/8.png?raw=true)\n![css2](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/9.png?raw=true)\n\n\n## Stylus + Stylus-loader\n\n> 推荐使用Stylus，语法简练。\n> 具体语法可参考[Stylus cheatsheet](https://devhints.io/stylus)\n\n\n## VConsole \n\n> 真机调试，在`main.js`里已配置。\n\n```js\n// 开发环境开启vConsole\nif (process.env.NODE_ENV !== 'production') {\n  const vConsole = new VConsole()\n  console.log(vConsole.version)\n}\n```\n![vconsole](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/6.jpg?raw=true)\n\n\n## Lodash  \n> 在`main.js`里注入到Vue的原型上，通过`this._`来调用。\n\n```js\nVue.prototype._ = lodash\n\n// @Example\nthis._.chunk(['a', 'b', 'c', 'd'], 2);\n// => [['a', 'b'], ['c', 'd']]\n```\n其它用法请浏览\n[lodash文档](https://www.lodashjs.com/docs/4.17.5.html)。\n\n\n## NProgress \n> 在`main.js`里引入样式文件\n\n```js\nimport 'nprogress/nprogress.css'\n```\n\n> 在`router.js`的钩子函数里根据不同场景做配置\n\n```js\n//  判断是否需要登录权限 以及是否登录\nrouter.beforeEach((to, from, next) => {\n  let userinfo = storage.get('userinfo')\n  // 判断是否需要登录权限\n  if (to.matched.some(res => res.meta.requireAuth)) { \n    // 判断是否登录\n    if (userinfo) { \n      next()\n    } \n    // 没登录则跳转到登录界面\n    else { \n      NProgress.start()\n      next({\n        path: '/Login',\n        query: { redirect: to.fullPath }\n      })\n    }\n  } else {\n    next()\n  }\n})\n\nrouter.afterEach(transition => {\n  NProgress.done()\n})\n```\n\n## axios  \n> axios除了接口请求，主要还做了拦截处理，利于接口数据异常统一管理，相关代码都在`src/api`文件夹内。\n\n请求拦截的逻辑放在`src/api/axios.js`里。\n\n```js\n// http请求拦截器<pendding>\nAxios.interceptors.request.use(\n  config => {\n    //...\n    // 以下的判断处理可根据具体需求场景做一些统一操作\n    const token = cookie.get('token')  \n    // 判断是否存在token，即判断用户是否登录\n    if (token) {\n      cookie.set('token', token, 1 / 12) // 用户每次操作，都将cookie设置成2小时\n      config.headers.Authorization = token // 每个http header都加上token\n    }\n    return config\n  },\n error => {\n    // do something \n  }\n)\n```\n所有的接口请求统一放在`src/api/index.js`里。\n\n```js\n// 首页信息\nexport const getHome = (params) => axios.get(HOST + 'home', params)\n```\n\n然后在`.vue`文件内使用如下\n```js\n<script type=\"text/ecmascript-6\">\nimport { getHome } from '@/api'\n\nexport default {\n    // do something....\n    methods:{\n        // 获取数据，私有方法尽量使用 _ 前缀\n        async _fetchData() {\n          const res = await getHome()\n          try {\n            const data = res.data\n            this.slideImgs = data.slideImgs\n          } catch (err) {\n            console.log('获取数据错误', err)\n          }\n        }\n    },\n    created(){\n        this._fetchData()\n    }\n}\n\n```\n\n## mock.js \n> 很多时候我们前端来定接口数据结构，`easy-mock`等在线工具也好用，但是经常出现不稳定，网址频繁挂掉。这里的moack主要引入[axios-mock-adapter](https://www.npmjs.com/package/axios-mock-adapter)，一样配合axios来做了拦截处理。mock的语法请参考官方文档[Mock](https://github.com/nuysoft/Mock/wiki)。\n\n所有的mock数据接口每条单独一份放在`src/mock/data`文件夹下，数据对象使用`common.js`语法暴露出来。\n\n```js\n// users.js\nmodule.exports = {\n  code: 10000,\n  message: 'success',\n  data: {\n    'list|100': [{\n      'id|+1': 1,\n      userName: '@cname()'\n    }]\n  }\n}\n```\n\n在`src/mock/index.js`里封装了一个`CreateInterface`类：\n```js\n    class CreateInterface {\n      constructor() {\n        this.SUCCESS_STATUS = 200 // 成功状态\n        this.FAIL_STATUS = 500 // 失败状态\n        this.mocker = new MockAdapter(Axios)\n        // mock接口列表，需要手动添加\n        this.interfaces = [\n          'users',\n          // more interface...\n        ]\n      }\n      init() {\n        const { interfaces, mocker, SUCCESS_STATUS } = this\n        interfaces.forEach(filename => {\n          mocker.onGet(filename).reply((config) => [SUCCESS_STATUS, Mock.mock(require(`./data/${filename}`))])\n        })\n      }\n    }\n```\n\n## .editorConfig\n> 可操作的配置虽然不多，但是能覆盖大部分情况。\n\n```bash\nroot = true #表明是最顶层的配置文件，发现设为true时，才会停止查找.editorconfig文件\n\n[*] # 对所有文件生效\ncharset = utf-8\nindent_style = space #tab为hard-tabs，space为soft-tabs\nindent_size = 2 #设置整数表示规定每级缩进的列数和soft-tabs的宽度\nend_of_line = lf #定义换行符，支持lf、cr和crlf\ninsert_final_newline = true #设为true表明使文件以一个空白行结尾，false反之\ntrim_trailing_whitespace = true #设为true表示会除去换行行首的任意空白字符，false反之\n```\n 编辑器一样还是推荐使用VsCode，里面有个插件支持可以安装下。\n![editorConfig for VsCode](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/2.png?raw=true)\n\n## vue-meta\n> 视情况使用，一般在PC端应用的相对比较多。在`main.js`里引入后全局注册。\n```js\nimport VueMeta from 'vue-meta'\n\n\n// 单独设置页面的title和meta信息\nVue.use(VueMeta)\n```\n\n具体在vue文件内使用方法如下\n```js\nexport default {\n  data() {\n    return {\n      pageTitle: '个人中心'\n    }\n  },\n  metaInfo() {\n    return {\n      title: this.pageTitle,\n      titleTemplate: '%s - Test',\n      script: [{ innerHTML: 'console.log(\"Hey!~~!\")', type: 'text/javascript' }]\n    }\n  }\n}\n```\n![title](https://raw.githubusercontent.com/kpengWang/Blog-images-storage/master/2018-08-17/3.png)\n\n![控制台console](https://github.com/kpengWang/Blog-images-storage/blob/master/2018-08-17/4.png?raw=true)\n\n\n## husky + lint-staged \n\n> 主要是在把 Lint 挪到本地，并且每次提交只检查本次提交所修改的文件，使用 `git commit -a`，或者先 `git add `然后 `git commit` 的时候，你的修改代码都会经过待提交区。\n\n主要配置在`package.js`配置文件里.\n```js\n{\n    \"script\":{\n        // ...\n        \"precommit\": \"lint-staged\"\n    }   \n    \"lint-staged\": {\n    \"src/**/*.{js,ts}\": [\n      \"standard --write\",\n      \"eslint --fix\",\n      \"git add\"\n    ]\n  },\n}\n\n```\n\n## vue-lazyload\n\n> 它其实就是注册一个全局指令，然后使用一个默认图片。\n\n\n```js\n//main.js\n\n// do something \nVue.use(VueLazyLoad, {\n  loading: require('./common/image/default.png')\n})\n// do something \n```\n\n``` html\n <img class=\"img\"  v-lazy=\"item.url\">\n```\n\n## vue-lazy-component\n\n> 引用这个插件具体解决做Seketon骨架屏效果。可配置的参数实用，效果不错。\n\n+ 支持 组件可见或即将可见时懒加载\n+ 支持 组件延时加载\n+ 支持 加载真实组件前展示骨架组件，提高用户体验\n+ 支持 真实组件代码分包异步加载\n\n- 具体文档参考[@xunlei/vue-lazy-component](https://www.npmjs.com/package/@xunlei/vue-lazy-component)。\n- [在线Demo效果](https://xunleif2e.github.io/vue-lazy-component/demo/dist/index.html#/)\n\n## vuex \n> 推荐直接阅读[vuex官方文档](https://vuex.vuejs.org/zh/guide/)。项目结构一样是使用的官方推荐的。\n\n\n## vuex-persistedstate \n\n>  数据持久化解决方案,主要使用场景是，页面刷新时当前页面的状态仍然可以保持。\n\n+ 当vuex状态发生改变时，自动同步保存到`localStorage`。\n+ 当重新加载页面vuex初始化时，自动将`localStorage`存储的数据作为初始状态加载。\n\n在`src/store/index.js`内引入插件并使用，无需其它操作。\n```js\n// index.js\n\nimport createPersistedState from 'vuex-persistedstate'\nimport * as storage from '@/utils/storage'\n\nexport default new Vuex.Store({\n  actions,\n  getters,\n  state,\n  mutations,\n  strict: debug,\n  // 状态持久化\n  plugins: [\n    createPersistedState({\n      storage: {\n        getItem: key => storage.get(key),\n        setItem: (key, value) => storage.set(key, value),\n        removeItem: key => storage.remove(key)\n      }\n    })\n  ]\n})\n```\n\n## vuex-router-sync\n> 主要是router的状态<path,query和params>存入vuex的state中；\n> 使用方式如下：\n```js\nstore.state.route.path   // current path (string)\nstore.state.route.params // current params (object)\nstore.state.route.query  // current query (object)\n```\n---\n# UI库\n\n## Cube-UI\n\n> cube-ui 是基于 Vue.js 实现的精致移动端组件库。推荐阅读[官方文档](https://didi.github.io/cube-ui/#/zh-CN/docs/introduction)。\n+ PC门户网站：使用[Muse-UI](https://muse-ui.org/#/zh-CN/installation)\n+ PC后台CMS：使用[vue-element-admin](https://panjiachen.github.io/vue-element-admin-site/zh/guide/)。\n\n常用的组件我们可以直接在`main.js`里全局注册\n\n```javascript\nimport {\n  // eslint-disable-next-line\n  Style,  // 引入 Style 加载基础样式\n  Loading,\n  Button,\n  Dialog,\n  Toast,\n  Scroll\n} from 'cube-ui'\n\nVue.use(Scroll)\nVue.use(Loading)\nVue.use(Button)\nVue.use(Dialog)\nVue.use(Toast)\n```\n\n---\n\n# Webpack优化\n\n> 与2.x相同，在根目录下新建了`build`文件夹。所有可以优化webpack相关的代码逻辑放入这里，仍然通过node环境变量来使用`webpack-merge`做逻辑合并。\n\n+ **webpack.base.conf.js** 共用的配置文件\n+ **webpack.dev.conf.js**  走开发环境的配置文件\n+ **webpack.prod.conf.js**  走生产环境的配置文件\n+ **config.js**           配置参数\n\n## Happypack \n> 通过多进程模型，来加速代码构建，代码在`webpack.prod.conf.js`文件中，主要使用了Happypack的`ThreadPool`方法，HappyThreadPool(“进程池”) 对象来管理生成的子进程对象。利用缓存来使得rebuild 更快。\n\n\n> 推荐阅读[happypack 原理解析](http://taobaofed.org/blog/2016/12/08/happypack-source-code-analysis/)。\n\n具体操作方法如下：\n\n```js\n// webpack.prod.conf.js\n\nconst OS = require('os')\nconst HappyPack = require('happypack')\nconst happyThreadPool = HappyPack.ThreadPool({ size: OS.cpus().length })\n\n  { \n  // do something...\n      plugins: [\n        new HappyPack({\n          id: 'happybabel',\n          loaders: ['babel-loader'],\n          threadPool: happyThreadPool,\n          cache: true,\n          verbose: true\n        })\n    ]\n  }\n```\n## webpack-parallel-unglify-plugin\n> webpack提供的UglifyJS插件由于采用单线程压缩，速度很慢； 使用`webpack-parallel-unglify-plugin`可以并行运行UglifyJS插件，这可以有效减少构建时间多线程压缩js。\n\n```js\n// webpack.prod.conf.js\nconst ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')\n\n  { \n  // do something...\n      plugins: [\n        new ParallelUglifyPlugin({\n          cacheDir: '.cache/',\n          sourceMap: false,\n          uglifyJS: {\n            output: { comments: false },\n            compress: { warnings: false }\n          }\n        })\n    ]\n  }\n```","readmeFilename":"README.md"}