Начать с нуля, телефон для создания библиотеки интерфейсных компонентов

Vue.js

Библиотека компонентов MI-vant

Создайте внутреннюю библиотеку компонентов. Когда мы рефакторим код и разрабатываем новые функции, мы извлекаем общедоступные компоненты, сокращаем повторное использование кода, фокусируемся на разделении бизнеса и компонентов, упрощаем связывание и облегчаем разработку и обслуживание.

адрес предварительного просмотра

Ма Цзюньчан.GitHub.IO/mi.van T/#/Пожалуйста…

Ма Цзюньчан.GitHub.IO/Mi.van T.Stone О…

характеристика

  • Поддержка по требованию
  • режим предварительного просмотра
    • режим предварительного просмотра сборника рассказов
    • Режим предварительного просмотра чистой уценки
  • рем-адаптация
  • Поддержка настройки темы
  • Более полная документация по использованию и примеры

Технический отбор

Сначала я рассматривал возможность использования конфигурации vue-cli3.0 vue-loader15+webpack4, а потом временно отказался, учитывая стабильность

  • Плагины и настройка с помощью babel7
  • Используйте less в качестве языка предварительной обработки для css в вашем проекте
  • Увеличьте метод упаковки свертывания
  • Внедрить сборник рассказов для поддержки функции предварительного просмотра проекта
  • Представьте vue-loader15
  • Введите связанные соединительные плагины, такие как Vue-Markdown-Loader для поддержки функции документа

babel7

Зачем переходить на babel7

Глобальная конфигурация Конфигурация в babel.config.js по умолчанию действует для всего проекта, включая node_modules. если не прошлоexcludeконфигурация, подлежащая устранению. Другими словами, у babel7 есть глобальные возможности настройки. Для фронтенда это большой шаг в сторону грамматики будущего, и когда он трансформировался в babel7, то столкнулся с множеством сложных проблем. Но в итоге устоял.

Примечания по обновлению
  1. Начиная с babel7, все официальные плагины и основные модули размещаются в пространстве имен @babel, что позволяет избежать проблемы с размещением имен, связанных с babel, в репозитории npm.

  2. Babel7 — это конфигурация, применимая ко всему проекту.

  3. Снятие заглушки перед этапом-х, отработанная заглушка babel-preset-es201x,

  4. Официальный инструмент обновления:babel-upgrade

    Когда я настраивал его раньше, я не знал, что есть этот инструмент, что привело ко многим окольным путям. Когда вы будете что-то делать в будущем, вы должны сначала проверить, есть ли инструменты. Избегая повторного сборки колес, вы также можете избежать множества ненужных ошибок.).

  5. Оптимизируйте код и используйте патч jsV8 для настройки производительности, и скорость компиляции ускорится.

  6. Версия babel-loader в webpack не ниже версии @babel/core, иначе компиляция выдаст ошибку

В vue-cli версии 2.9.6 для 🌰 по умолчанию используется .babelrc.

Конфигурация и связанные с ней зависимости в .babelrc

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

  • Конфигурация в package.json
    "babel-helper-vue-jsx-merge-props": "^2.0.3",
    "babel-loader": "^7.1.1",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-plugin-transform-vue-jsx": "^3.5.0",
    "babel-preset-env": "^1.3.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-2": "^6.22.0",
    "@babel/core": "^7.5.5",

Конфигурация и связанные с ней зависимости в окончательной версии babel.config.js в mivant

module.exports = function (api) {
  api.cache(true);

  const presets = [
    "@babel/preset-env",
    "@vue/babel-preset-app",
    [
      '@vue/babel-preset-jsx',
      {
        functional: false
      }
    ]];
  const plugins = [
    "@babel/plugin-transform-runtime",
    '@babel/plugin-transform-object-assign',
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']];

  return {
    presets,
    plugins
  };
}

использованная литература

Выпущен Babel7

Разница между babelrc и babel.config.js

Обновление до Babel7

Простое руководство по обновлению для babel7

Читайте логику загрузки конфигурационного файла babel7 в одной статье

Краткое руководство по Babel

официальный сайт бабель

Все компоненты загружаются и загружаются по запросу

Как загружаются компоненты?

Интерпретация исходного кода vue.use

   Object.keys(components).forEach((key)=>{
     Vue.component(components[key].name,components[key])
   })

Прикрепите код в index.js

  • импортировать связанные компоненты
  • Предоставьте общедоступный метод установки
  • Вся загрузка осуществляется экспортом по умолчанию, а загрузка по требованию реализуется путем экспорта
import MiButton from './Button/index'
import Modal from './Modal/index'


const components = [
  MiButton,
  Modal
]

const version = '1.0.0'

const install = function (Vue) {
  if (install.installed) return
  components.forEach(item => {
    Vue.component(item.name, item)
  })
}


if (typeof window !== 'undefined' && window.Vue) {
  console.log('运行环境为window');
  install(window.Vue)
}

export {
  MiButton,
  Modal,
  install
}

export default {
  install,
  version
}

Первый способ загрузки по запросу
// 组件中内置了单个组件所需的样式  无需配置babel-plugin-import
 import { MiButton, Modal } from 'miVant'
 import Vue from 'vue'

 Vue.use(MiButton)
 Vue.use(Modal)

babel-pluhin-import

Второй способ загрузки по запросу
import MiButton from 'miVant/lib/Button'
import Modal from 'miVant/lib/Modal'
import Vue from 'vue'

 Vue.use(MiButton)
 Vue.use(Modal)

Основы загрузки в стойку по требованию

  • Вставьте соответствующий файл vue в index.js в компоненте и укажите метод установки.
  • Файл less представлен в файле XX.vue, а файл less встроен
  • При упаковке используйте CopyWebpackPlugin для копирования файлов компонента в каталог lib, что является вторым способом загрузки по запросу.

использование меньше

  • Настройте less-loader в utils Обратите внимание на правила разбора загрузчика

Пример употребления less в приложении

@hd: 1px; // 基本单位

// 支付宝钱包默认主题
// https://github.com/ant-design/ant-design-mobile/wiki/设计变量表及命名规范

// 色彩
// ---
// 文字色
@color-text-base: #000;                  // 基本
@color-text-base-inverse: #fff;          // 基本 - 反色
@color-text-secondary: #a4a9b0;          // 辅助色
@color-text-placeholder: #bbb;           // 文本框提示
@color-text-disabled: #bbb;              // 失效
@color-text-caption: #888;               // 辅助描述
@color-text-paragraph: #333;             // 段落
@color-link: @brand-primary;             // 链接


@defaultColor: #455a64;
@hoverColor:#1989fa;
@height: 60px;

.navTitle{
  font-size:16px;
  font-weight:600;
  cursor: default;
}
.navItem {
  color: @defaultColor;
  font: 14px/24px PingFang SC;
  padding: 10px 10px 10px 50px;
  text-align: left;
  cursor: pointer;
}


.doc-nav-title,
.doc-comp-title{
  .navItem();
  .navTitle();
}

.doc-nav-item{
  .navItem()
}

.doc-comp-item{
  .navItem()
}

Введенная функция предварительного просмотра сборника книги

Прежде всего, что такое история книги?
  1. Storybook — это инструмент, помогающий в разработке элементов управления пользовательского интерфейса. Создавайте независимые элементы управления с помощью истории, чтобы каждая разработка элемента управления имела независимую среду разработки и отладки, вы могли просматривать различные состояния каждого компонента по отдельности, а также интерактивно разрабатывать и тестировать компоненты.
  2. Работа Storybook не зависит от проекта, и разработчикам не нужно беспокоиться о невозможности разработки элементов управления из-за проблем со средой разработки и зависимостями.
  3. Storybook поддерживает множество основных фреймворков (React, Vue, Angular).
  4. В январе 2019 года сборник рассказов выпустил версию 5.0, первую серьезную корректировку с момента запуска проекта. Улучшенные слои просмотра, плагины и интеграции в экосистеме.
Установите и используйте
  1. Руководство по установкеstorybook for vue

  2. Пользовательская конфигурация WebPack, решение проблем с расширениями и проблем с компиляцией LESS

    // 自定义webpack配置
    const path = require('path');
    
    
    module.exports = async ({ config, env }) => {
    
      // Extend it as you need.
      function resolve(dir) {
        return path.join(__dirname, '..', dir);
      }
    
      config.resolve = {
        extensions: ['.js', '.vue', '.json', '.jsx'],
        alias: {
          'vue$': 'vue/dist/vue.esm.js',
          '@': resolve('src')
        },
      }
      config.module.rules.push({
        test: /\.stories.jsx?$/,
        loaders: [require.resolve('@storybook/addon-storysource/loader')],
        enforce: 'pre',
      });
      config.module.rules.push(
        {
          test: /\.(css|less)$/,
          use: [{
            loader: 'style-loader', // creates style nodes from JS strings
          }, {
            loader: 'css-loader',// translates CSS into CommonJS
          },
          { loader: 'postcss-loader' },
          {
            loader: 'less-loader',
            options: {
              javascriptEnabled: true
            } // compiles Less to CSS
          }],
          exclude: /node_modules/
        })
    
    
      return config;
    };
    
    
  3. В Storybook 5.0 используется vue-loader15, для синтаксического анализа и компиляции по умолчанию используется babelrc, а babelrc необходимо настроить

    {
      "presets": [
        "@babel/preset-env",
        "@vue/babel-preset-app",
        [
          "@vue/babel-preset-jsx",
          {
            "functional": false
          }
        ]
      ]
    }
    
    
Как настроить среду Storybook для компонентов
  • Создайте новый файл xx.js в каталоге stories, который сопоставляется с левым каталогом предварительного просмотра в среде предварительного просмотра.

  • Внесите компоненты vue в файл xx.js и напишите тестовые примеры. Связанные функции плагина вводятся через функцию addDecorator.

    import { storiesOf } from '@storybook/vue';
    import { withKnobs } from '@storybook/addon-knobs';
    import miVantButton from '../src/components/Button/Button.vue'
    import { withStorySource } from '@storybook/addon-storysource'
    import buttonText from '../docs/button.md'
    
    const simpleSourceCode = '<mi-vant-button>storyBook</mi-vant-button>'
    storiesOf('miVantButton', module)
      .addDecorator(withKnobs)
      .addDecorator(withStorySource(simpleSourceCode))
      .addParameters({
        readme: {
          sidebar: buttonText,
        },
      })
      .add('with text', () => {
        return {
          components: { miVantButton },
          template: `<mi-vant-button>storyBook</mi-vant-button>`,
        }
      },
        {
          notes: {
            markdown: buttonText
          }
        }
      )
    
  • В папке .storybook в корневом каталоге

    • Зарегистрируйте связанные плагины в addons.js

    • Настройте разрешенную среду в config.js и установите глобальный плагин. Похоже на main.js проекта vue

      import { configure, addDecorator, addParameters } from '@storybook/vue';
      import { withNotes } from '@storybook/addon-notes'
      import { addReadme } from 'storybook-readme/vue';
      import { setOptions } from '@storybook/addon-options'
      import { Button } from 'vant'
      import Vue from 'vue'
      
      Vue.use(Button)
      
      
      const req = require.context('../stories', true, /\.js$/)
      
      function loadStories() {
        req.keys().forEach((filename) => req(filename))
      }
      
      setOptions({
        name: 'mi-Vant',
        url: '#',
        goFullScreen: false,
        showStoriesPanel: true,
        showAddonPanel: true,
        showSearchBox: true,
        addonPanelInRight: true,
        sortStoriesByKind: false,
        hierarchySeparator: null,
        hierarchyRootSeparator: null,
        sidebarAnimations: true,
        selectedAddonPanel: undefined,
      })
      
      addParameters({
        viewport: { defaultViewport: 'galaxys5' },
      })
      addDecorator(addReadme);
      addDecorator(withNotes)
      // require
      configure(loadStories, module);
      
      

возникшие проблемы

  • Проблема использования версии vue-loader

    • Новая версия по умолчанию поддерживает vue-loader15, а vue-loader в проекте — 13.3.0. В то время я думал, что vue-loader15 нужно использовать с webpack4, поэтому я понизил версию storybook.

    • Нижняя версия сборника рассказов по умолчанию использует babel6, может анализировать только .babelrc и требует настройки конфигурации веб-пакета, поэтому можно использовать только пользовательскую конфигурацию babel и веб-пакета, представленную в сборнике рассказов.

    • Основные настройки все настроены.При введении плагина обнаруживается, что плагин нельзя использовать.......Неизвестная ошибка очень раздражает......., синтаксис ошибка будет предложено. На самом деле сконфигурированный нами babel был проанализирован, но все равно сообщает об ошибке. . . . Думаю, это как-то связано с версией плагина.

      ReferenceError:  regeneratorRuntime is not defined
      

      image.png

  • При импорте библиотеки vant по запросу сообщалось об ошибке css-loader

    Решение: добавить исключить

     config.module.rules.push(
        {
          test: /\.(css|less)$/,
          use: [{
            loader: 'style-loader', // creates style nodes from JS strings
          }, {
            loader: 'css-loader',// translates CSS into CommonJS
          },
          { loader: 'postcss-loader' },
          {
            loader: 'less-loader',
            options: {
              javascriptEnabled: true
            } // compiles Less to CSS
          }],
          exclude: /node_modules/
        })
    
  • Наконец выбрали текущую стабильную версию, изменили соответствующую конфигурацию и ввели соответствующие плагины.

связанные плагины
имя плагина Функция Примечание
@storybook/addon-notes Добавьте заметки к компоненту и украсьте историю Аннотация Текстовая информация
@storybook/addon-actions Отображение данных о событии
@storybook/addon-backgrounds Изменить цвет фона страницы
@storybook/addon-storysource Показать исходный код компонента
@storybook/addon-knobs Динамический реквизит
storybook-readme Импортировать уценку как историю
@storybook/addon-viewport/register Добавлен режим предварительного просмотра на мобильных устройствах.
@storybook/addon-options Выбор панели конфигурации

Связанная документация

решение для обновления vue-loader

Storybook 3.2 представляет поддержку Vue.js

сборник рассказов для официального сайта vue

@storybook/vue npm

Сборник рассказов 5.0 официально выпущен: самое большое изменение в истории

Представляем упаковку Rollup

представлять

Rollup — это сборщик модулей JavaScript, который компилирует небольшие фрагменты кода в большие сложные фрагменты кода, такие как библиотеки или приложения. Собственный модульный механизм es6 используется для упаковки и сборки модулей, и размер пакета после компиляции будет меньше.

Подробнее читайте в моей предыдущей статье

Первое знакомство с роллапом

Проблемы после введения
  • Отчет об ошибках кросс-окружения
sudo npm install --global cross-env
  • Упаковка роллапа, если вы используете babel.config.js+babel7, ям больше... Иногда будут какие-то неизвестные ошибки

Студентам, которые хотят попробовать, рекомендуется использовать такую ​​конфигурацию, как babel6 + babelrc.

chenshenhai.GitHub.IO/roll upmetal-нет…

  • Когда rollup-plugin-vue находится в более ранней версии 0.68, он сообщит об ошибке, что входная запись не может быть найдена Текущая версия накопительного пакета в проекте — V1.19.3.

Прикрепленный файл rollup.config.prod.js

import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import buble from 'rollup-plugin-buble'
import replace from 'rollup-plugin-replace';
import { uglify } from 'rollup-plugin-uglify';
import vue from 'rollup-plugin-vue'
import postcss from 'rollup-plugin-postcss';
const path = require('path');

const ENV = process.env.NODE_ENV;
const resolveFile = function (filePath) {
  return path.join(__dirname, './', filePath)
}


export default {
  input: resolveFile('src/components/index.js'),
  output: {
    dir: 'es',
    format: 'umd',
    name: 'miVant',
    exports: 'named',
  },
  plugins: [
    resolve({ extensions: ['.js', '.vue'] }),
    postcss({
      extensions: ['.less', '.css'],
      use: [
        ['less', {
          javascriptEnabled: true
        }]
      ],
      extract: true,
      minimize: true,
    }),
    vue({
      template: {
        isProduction: true
      },
      css: false
    }),
    commonjs(),
    buble({
      objectAssign: 'Object.assign'
    }),
    replace({
      exclude: 'node_modules/**',
      ENV: JSON.stringify(process.env.NODE_ENV),
    }),
    (ENV === 'production' && uglify()),
  ],
};

Оставьте вопрос: роллап завершает загрузку упаковки по требованию

Разбор уценки Vue

I want

  1. Компоненты преобразования файлов readme для использования компонентов документа
  2. Подобно текущим известным библиотекам компонентов, таким как antd, element-ui, vant и другим, библиотека кода поддержки выделена, отображение и другие компоненты динамических эффектов, короткое предложение: возможность запуска кода в md.
  3. Сделайте нашу библиотеку компонентов менее низкой 😁........

Так как раньше я не сталкивался с подобными функциями, начался долгий путь исследований. . . .

  • Разработанный автором Vue-press vue, имитирующий стиль vue, он подходит для статических документов, но не может очень хорошо отображать эффект предварительного просмотра.Документация vuePress на китайском языке
    • Подобно hexo, его могут использовать студенты, которые хотят создать личный блог.
  • vue-markdown-loader с vue-loader может реализовать динамическую компиляцию документов md
    • При использовании версии vue-loader15 необходимо обратить внимание на совместимый метод записи
    • С серией markdown-it вполне можно расширить md
    • Следует отметить, что когда Vue-markdown-loader используется с vue-loader15, следует обратить внимание на способ написания загрузчика.
    • Темы, использующие highlight.js, поддерживают динамическую настройку тем.

Прикрепите правила разбора уценки в webpack

{
        test: /\.md$/,
        use: [
          {
            loader: 'vue-loader'
          },
          {
            loader: 'vue-markdown-loader/lib/markdown-compiler',
            options: {
              raw: true,
              preventExtract: true,
              use: [
                [
                  require('markdown-it-container'),
                  'demo',
                  {
                    validate: function (params) {
                      return params.trim().match(/^demo\s+(.*)$/)
                    },
                    render: function (tokens, idx) {
                      if (tokens[idx].nesting === 1) {
                        // 1.获取第一行的内容使用markdown渲染html作为组件的描述
                        let demoInfo = tokens[idx].info.trim().match(/^demo\s+(.*)$/)
                        let description = demoInfo && demoInfo.length > 1 ? demoInfo[1] : ''
                        let descriptionHTML = description ? markdownRender.render(description) : ''
                        // 2.获取代码块内的html和js代码
                        let content = tokens[idx + 1].content
                        // 3.使用自定义开发组件【DemoBlock】来包裹内容并且渲染成案例和代码示例
                        return `<demo-block>
                        <div class="source" slot="source">${content}</div>
                        ${descriptionHTML}
                        <div class="highlight" slot="highlight">`
                      } else {
                        return '</div></demo-block>\n'
                      }
                    }
                  }
                ]
              ]
            }
          }
        ]
      },

Вручную дополнить функцию копирования в демо-блоке

<template>
  <div class="demo-block">
    <div class="demo-block-source">
      <slot name="source"></slot>
      <span class="demo-block-code-icon" v-if="!$slots.default" @click="showCode=!showCode">
        <img
          alt="expand code"
          src="https://gw.alipayobjects.com/zos/rmsportal/wSAkBuJFbdxsosKKpqyq.svg"
          class="code-expand-icon-show"
        />
      </span>
    </div>
    <div class="demo-block-meta" v-if="$slots.default">
      <slot></slot>
      <span v-if="$slots.default" class="demo-block-code-icon" @click="showCode=!showCode">
        <img
          alt="expand code"
          src="https://gw.alipayobjects.com/zos/rmsportal/wSAkBuJFbdxsosKKpqyq.svg"
          class="code-expand-icon-show"
        />
      </span>
    </div>
    <div class="demo-block-code" v-show="showCode">
      <p class="copy" @click="copy">复制</p>
      <slot name="highlight"></slot>
    </div>
  </div>
</template>
<script type="text/babel">
export default {
  data() {
    return {
      showCode: false
    };
  },
  methods: {
    copy(e) {
      const hightext = e.target.nextElementSibling;
      const input = document.createElement("input");
      document.body.appendChild(input);
      let value = hightext.innerText;
      input.value = value;
      input.select();
      if (document.execCommand("copy")) {
        document.execCommand("copy");
        console.log("复制成功");
      }
      document.body.removeChild(input);
    }
  }
};
</script>
<style lang='less'>
@import "./less/demo-block.less";
.copy {
  cursor: pointer;
  position: absolute;
  right: 10px;
  top: 0;
}
</style>

Связанная документация

VuePress научит вас создавать технический документ/блог в стиле Vue.

От Vue-cli для создания библиотеки пользовательского интерфейса до Markdown для создания документации и демонстрационных примеров.

vue-markdown-loader

markdown-it-container

vue-markdown-loader error with vue Loader 15

rem адаптация + пользовательская тема

адаптационная функция рем

  • Автоматически конвертировать единицы px в единицы rem с помощью postcss-px2rem

  • Установите правила преобразования через .postcssrc.js в корневом каталоге проекта.

    // https://github.com/michael-ciniawsky/postcss-load-config
    
    module.exports = {
      "plugins": {
        "postcss-import": {},
        "postcss-url": {},
        // to edit target browsers: use "browserslist" field in package.json
        "autoprefixer": {
          browsers: ['Android >= 4.0', 'iOS >= 7']
        },
        "postcss-px2rem": { remUnit: 100 }
      }
    }
    
    
  • Дополните соответствующий размер шрифта в css

    @import './var.less';
    
    html {
      font-size: 100px; /* no */
    }
    h1{
      font-size: 32px;
    }
    h2{
      font-size: 24px;
    }
    h3{
      font-size: 19px;
    }
    h4{
      font-size: 16px;
    }
    h5{
      font-size: 14px;
    }
    h6{
      font-size: 13px;
    }
    
    li,p,th,td {
      font-size: 16px;
    }
    
    

Пользовательские темы

МиВант б/уLessСтиль предварительно обработан, а некоторые переменные стиля встроены.Вы можете настроить нужную тему, заменив переменные стиля.

Файл конфигурации: ~/src/components/less/var.less

@primary-btn-color :#fbb212;

пользовательский метод

  1. используя меньше предоставляемыхmodifyVarsПеременные могут быть изменены.Ниже приведена эталонная конфигурация веб-пакета.
  2. Вот пример каталога /build/utils версии scaffold vue2.x
exports.cssLoaders = function (options) {
  options = options || {}

  const lessLoader = {
    loader: 'less-loader',
    options: {
      sourceMap: options.sourceMap,
      modifyVars: {
        color: 'red'
      }
    }
  }
  const lessConfig = {
    modifyVars: {
      primary-btn-color: 'red'
    }
  };


  const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  const postcssLoader = {
    loader: 'postcss-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  // generate loader string to be used with extract text plugin
  function generateLoaders(loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader, lessLoader] : [cssLoader, lessLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less', lessConfig),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

Проект запущен и работает

// 克隆项目到本地
git clone  https://github.com/majunchang/mi-vant.git
// 切换到master分支
// 安装相关依赖
 npm  i

//  npm 脚本
// storybook 预览模式
 "start": "npm run storybook",
 "storybook": "start-storybook -p 9001 -c .storybook",
// 打包storybook静态文件
 "build-storybook": "build-storybook -c .storybook",
// 文档预览 端口是8081
 "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
// 打包之后的依赖包分析
 "bundle-report": "webpack-bundle-analyzer --port 8123 dist/stats.json",
// webpack build
 "build": "node build/build.js",
// rollup 编译
 "clean": "rimraf rollupDist",
 "rollup": "cross-env NODE_ENV=production rollup --config=rollup.config.prod.js"