Используйте webpack4 для создания библиотеки компонентов на основе Vue.

внешний интерфейс JavaScript Vue.js Webpack

Несколько проектов в группе имеют одни и те же общие компоненты, поэтому мы начали строить общедоступную платформу для разработки компонентов и впервые разработали библиотеку, так что это был эталон.iviewконфигурация для сборки. запишите, как использоватьwebpack4построить одинlibraryстроительные леса

предисловие

Чтобы использовать webpack4, вам необходимо установить webpack и webpack-cli

yarn add webpack webpack-cli -D

Затем идет запись файла конфигурации.

Строительные леса проекта

Структура каталогов библиотеки, которую я написал, выглядит следующим образом, только для справки, в основном для имитацииiviewСтруктура , некоторые из которых относятся к конфигурацииvue-cliконфигурационный файл веб-пакета.

├─build
│      build.js  // 用于执行构建
│      check-versions.js    // vue-cli 留下的,主要就是检查npm版本和node版本
│      webpack.base.conf.js   // 通用配置
│      webpack.dev.conf.js   // 开发环境
│      webpack.dist.prod.conf.js //  用于生成library的代码 -- hbf.min.js
│      webpack.prod.conf.js  // 用于生成example文件的打包代码,这个其实是没有必要的.
│
├─dist
│   └─example // example生成的打包文件夹,可以通过githubPage来预览,或者本地使用anywhere预览
│     hbf.min.js // library 文件
│
├─example    // example目录
│      App.vue
│      index.html
│      main.js
│
├─lib
│  │  index.js  // 全量引入公共组件,并暴露出来,包含install方法可供vue引入使用该插件
│  │  README.md
│  │  
│  └─components // 公共组件
│
├─package.json  // 项目包依赖

Более конкретную информацию можно найти наgithubСкладское чтение.

Скомпилировано WebPack

Для лучшего понимания давайте сначала разберемся с скомпилированным кодом webpack.

Код, обрабатываемый webpack, обычно выглядит так

// webpack编译后的代码

/*
* @param {Array} modules
*/
;(function(modules) {
  function __webpack_require__(moduleId) {
    var module = {
      i: moduleId, // 模块ID
      l: false,
      exports: {}, // 作为结果返回.
    }
    // 调用modules数组的某个元素(类型为函数)
    modules[moduleId].call(
      module.exports,
      module,
      module.exports,
      __webpack_require__
    )
    return module.exports
  }

  return __webpack_require__(0)
})([
  /** 省略了代码, 该数组的每一项代表一个模块,实际是一个函数,接受三个参数,module对象,module.exports对象,__webpack_require__函数 **/
])

Общая структура скомпилированного кода webpack представляет собойIIFE函数, принимаетmodules: Arrayпараметр.

Для обработки модуля либоES Moduleизimportещеcommonjsизrequireпревращаются в__webpack_require__Эта функция для импорта модуля.

__webpack_require__функция, отmodulesПервый элемент массива стартует (moduleId равен 0, то есть входной файл), выполняет логику модуля (фактически функцию) и использует поступающиеmodule.exportsТип данных является ссылочным типомObject, косвенно даваяmodule.exportsДобавьте свойства.

return __webpack_require__(0)

Начиная с входного файла, импортируйте зависимые модули один за другим и, наконец, вернитесь к входному модулю.module.exports

В настоящее время на скомпилированный файл js не могут ссылаться другие модули, и он действителен только в текущей области.webpackОн предоставляет способ создания библиотеки, т. е. вoutputопределено вlibraryа такжеlibraryTarget. Сделайте встроенный js доступным для импорта и использования другими модулями.

установить конфигурацию библиотеки

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

// webpack.dist.pord.conf.js

output: {
  path: path.resolve(__dirname, '../dist'),
  publicPath: '/dist/',
  filename: 'hbf.min.js',
  library: 'hbf',
  libraryTarget: 'umd'
},

libraryМожет быть строкой или объектом (количество объектов ограниченоlibraryTargetценностьumdиспользуется в случае)

output: {
  library: {
    root:'Hbf',  // 暴露给全局变量,window.Hbf进行调用
    commonjs: 'hbf-public-components'
  },
  libraryTarget: 'umd'
}

commonjsа такжеcommonjs2разница.

commonjsСпецификация определяетexportsобъект иnodejsкогда понял,commonjsНа основании спецификации были сделаны некоторые расширения для определенияmodule.exports, который также называетсяcommonjs2Технические характеристики.

Когда мы обращаемся к библиотекам других людей, мы обычно можем импортировать их разными способами, например,<script>Знакомство с этикеткой черезcommonJSимпорт модуля, черезES6 ModuleПредставлять.

libraryTargetУстановить какumd(Общая спецификация модуля), библиотека может быть загружена различными методами загрузки модуля после упаковки с высокой совместимостью. оlibraryTargetДля получения подробной информации см.официальная документация по веб-пакету

библиотечные зависимости

Если наша библиотека разрабатывается на основе какой-то библиотеки, например, напишите библиотеку на основеvueБиблиотека компонентов пользовательского интерфейса при разработке этой библиотеки компонентов нам необходимо ввестиvue, если пользователь, который использует эту библиотеку компонентов, уже представил ееvue,Такvueбудет представлен и упакован дважды, поэтому мы разрабатываемlibraryКогда для некоторых зависимых модулей его можно импортироватьlibraryпредоставляемые пользователями. Итак, нам нужно удалить зависимые модули в упакованной сборке библиотеки.

externalsроль, предотвращая некоторыеimportПакеты упакованы в пакеты, но эти зависимости расширения получаются извне во время выполнения.

установивexternals, с выходаbundleисключатьvueа такжеiview.

Эти внешние зависимости могут быть в любой из следующих форм.

  • rootглобальный доступ к переменной
  • commonjsкакcommonjsимпорт модуля
  • commonjs2а такжеcommonjsАналогично, но экспортmodule.exports
  • amdиспользоватьamdвведение спецификации модуля
// webpack.dist.pord.conf.js

externals: {
  vue: {
    root: 'Vue',
    commonjs: 'vue',
    commonjs2: 'vue',
    amd: 'vue'
  },
  iview: {
    root: 'iView',
    commonjs: 'iview',
    commonjs2: 'iview',
    amd: 'iview'
  }
},

Кроме того, добавьте еще один в package.jsonpeerDependenciesПоле, роль условностьlibraryНомер версии зависимой библиотеки, которая загружается и используется пользователем.library, если зависимыйiviewа такжеvueНомер версии неверный, будет выдано предупреждение.

// package.json
"peerDependencies": {
  "iview": ">2.0.0",
  "vue": ">2.0.0"
},

Для этих двух зависимостей пропишите их в зависимостях среды разработки, иначе они будут установлены в директорию библиотеки во время установки.vueа такжеiview, что также не соответствуетlibraryреферер предоставилlibraryзависит от этой идеи.

vue библиотека плагинов/библиотека компонентов

Для библиотеки плагинов/компонентов vue, если вы хотите представить ее глобально, вам нужно иметьinstallметод. Внутренняя логика установки передается через параметрыvueobject для регистрации всех компонентов. Затем, наконец, соберите все общие компоненты вместе сinstallМетоды составляют новый выставленный объект.

// 引入公共组件
import publicMenu from './components/public-menu'
import tablePage from './components/table-page'
import sliderCustom from './components/slider-custom'

const components = {
  publicMenu,
  tablePage,
  sliderCustom,
}
const Hbf = Object.assign({}, components)
const install = function(Vue, opts) {
  if (install.installed) return

  Object.keys(components).forEach(component => {
    Vue.component(component, component)
  })
}

// 用于script标签引入
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

// 将install方法赋给Hbf对象
Hbf.install = install

// 输出default变量,用于全量引入,也可以在引入的时候选择使用 * 来全量引入
export default Hbf
// 输出各个组件,用于按需引入
export { publicMenu, tablePage, sliderCustom }

Выставляя объект с помощью метода установки, вы сначала используетеmodule.exports, сообщается об ошибке при обращении к библиотекеUncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'.

Потому что мой тестовый проект закрытbabelправильноES Moduleкомпиляция, как правило, без закрытия вручную,babelбудуES6 ModuleКомпилировать вcommonjsТехнические характеристики. настолько закрытыmoduleВ случае преобразования, поскольку вывод библиотеки используетcommonjsнормативныйmodule.exports, Введена спецификация библиотечного модуля ES6importКлючевое слово, в нем была ошибка, я экспортирую написанную библиотекуexportКлючевое слово, ошибки нет.

Я узнал, что большинство библиотек теперь используютcommonjsспецификации, из-заwebpackизtree-shakingтолько правильноES Moduleворваться. а такжеwebpackизtree-shakingна самом деле поUglylifyбыть реализованным.

Таким образом, спецификация модуля библиотеки может использовать два вида, используяpackage.jsonизmainа такжеmoduleПоля определяют файлы ввода для двух спецификаций модулей библиотеки соответственно.mainиспользуетcommonjsДокумент, написанный в канонической грамматике, в то время какmoduleэто использоватьES6 moduleГрамматически написанный документ,moduleПоле все еще предложение. Так принятоES2015Синтаксис модуля библиотеки, когда мы используем толькоlibraryЧасть кода, которую вы можете использоватьwebpackпровестиtree-shaking, удалите неиспользуемый код и уменьшите размер упакованных файлов.

Опубликовать пакет npm

Во-первых, вам нужно зарегистрировать учетную запись npm.

Если вы использовали зеркалирование Taobao раньше, вам нужно сначала вернуться к официальному источнику npm. В противном случае посылка не будет отправлена.

открыть командную строку

Переключить официальный источникnpm config set registry https://registry.npmjs.org/

воплощать в жизньnpm login, затем введите данные своей учетной записи.

можно настроить.npmignoreИгнорируйте некоторые файлы, которые не нужно загружать, и пишите так же, как.gitignoreтакой же.

Необходимо убедиться, что проект имеет правильныйpackage.jsonдокументы иREADME.mdдокумент

затем выполнитьnpm publishДелай пакет.

После отправки пакета вы можете вернуться к зеркальному источнику Taobao.

npm config set registry https://registry.npm.taobao.org

Библиотека эталонных компонентов

Введение тега скрипта

В начале я поместил файл JS в локальный тест и обнаружил, что вHTMLПервая строка файла сообщает об ошибке,Unexpected token <,StackOverflowПричина в том, что путь импорта неверный, поэтому я помещаю JS-файл на CDN,

<script src="http://osuuzm0m8.bkt.clouddn.com/hbf.min.js"></script>
<script>  
  console.log(window.Hbf) // 会看到你导出的对象
</script>

выход

полное цитирование

Может использоваться как любая другая библиотека плагинов/компонентов vue.

import hbf from 'hbf-public-components'

// 使用use方法触发hbf的intall方法,注册全部组件
Vue.use(hbf)

Если не экспортируетсяdefaultпеременные, используйте другой метод для полного импорта

import * as hbf from 'hbf-public-components'

Цитирование по запросу

import { publicMenu } from 'hbf-public-components'

Цитировать по требованию, если библиотека используетES2015 Moduleспецификация, никаких плагинов устанавливать не нужно, webpack их обработаетtree-shaking, удалить неиспользуемый код.

Как упоминалось ранее,webpackизtree-shakingКUglylifyПлагин реализован, нахожусь в среде разработки, не включенUglylifyдля сжатия кода, поэтому глядя на схему упаковки модулей, вы обнаружите, что вся библиотека импортирована, хотя я импортировал только один компонент.webpack4Только в производственной средеtree-shaking,настраиватьmodeценностьproductionЭто позволит оптимизировать производственные среды.

при использованииcommonjsКаноническая библиотека требует поддержки плагинов,babel-plugin-import. ПлагинantОфициально разработан. Импорт по запросу многих библиотек компонентов пользовательского интерфейса также зависит от этого плагина.

Установить

yarn add babel-plugin-import -D

Исправлять.babelrcдокумент,

"plugins": [
  ["import", {
    "libraryName": "hbf-public-components",
    "libraryDirectory": "lib/components"
  }]
],

Суммировать

На самом деле, если он не очень стабилен для迭代更新из公用组件库Например, неудобно использовать пакет npm, а можно использовать часто обновляемый публичный код компонента.Git subtree(руководство), вы можете подождать до определенного момента, когда общедоступная библиотека компонентов станет стабильной, прежде чем рассматривать возможность выпуска пакета npm.

При разработке библиотеки компонентов вы также можете использоватьrollup.jsПриходите строить леса,rollup.jsПо умолчанию используетсяES2015 Module, статический анализ может быть выполнен для удаления кода, на который нет ссылок,tree-shakingСлишкомrollup.jsпредложил первым.Rollupв сравнении сWebpack, который больше подходит для строительстваlibrary,Vue.jsэто использоватьRollupпостроен.WebpackОн имеет преимущества в разделении кода, поэтомуwebpackОтносительно подходит для создания приложений, но также возможно использование веб-пакета для сборки библиотек.

Этот проект также можно использовать в качестве общей основы для библиотеки сборки веб-пакета. попробуй в следующий разRollupпостроить библиотеку

Обсудите любые вопросы.

адрес проекта:github

адрес нпм:npm

Если для пары webpack и babelES ModuleЕсли вы не очень знакомы с обработкой, то можете прочитать следующую статью, она очень приятная.

О спецификации модуля и о том, как webpack, babel компилирует и преобразовывает модуль