Напишите простой JS SDK с помощью webpack

внешний интерфейс JavaScript API Webpack

введение

В последнее время в проекте необходимо предоставить упакованный JS SDK.Хотя это очень простая функция в настоящее время, она все же выбрана для удобства обслуживания и расширения в будущем.webpackВ качестве инструмента упаковки, в качестве справки, порекомендуйте хорошую статью, заинтересованные друзья могут сначала прочитать ее.

JavaScript SDK Design Guide(китайский перевод:Рекомендации по разработке JavaScript SDK)

Цель

В качестве SDK я хочу достичь следующей цели

  • предоставить схему загрузки
  • Воздействие общей переменной, лучше поддерживать различные нагрузки
  • Доступен в несжатой и сжатой версиях
  • Индивидуальные версии доступны для разных партнеров
  • На внутреннюю реализацию ссылаются модули, что удобно для расширения

Далее пошагово как пройтиwebpackвыполнить

Подготовить

Если нам, наконец, нужно предоставить SDK следующим образом

// 引用
<script type="text/javascript" src="http://xxx.com/sdk.js"></script>

// 使用
window.SDK.Shop.getList()       // 获取门店信息列表
window.SDK.Store.getById()      // 通过ID获取商品信息

Тогда список файлов должен быть примерно следующим.

|
| - package.json
| - webpack.config.js
| - node_modules
| - src
    | - index.js
    | - lib
        | - shop.js
        | - store.js
| - dist
| - build.js

webpackпройти черезindex.jsИмпортируйте упакованные файлы и поместите их вdistпапку, код некоторых ключевых файлов должен быть следующим

webpack.config.js

let path = require('path')
let webpack = require('webpack')

module.exports = {
    entry: {
        'sdk': ['./src/index.js']
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    }, 
    // 压缩混淆 js
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: true
        })
    ]
}

shop.js

module.exports = {
    getList: function () {
        .....
    }
}

store.js

module.exports = {
    getById: function (id) {
        .....
    }
}

index.js

var Shop = require('./lib/shop.js')
var Store = require('./lib/store.js')

module.exports = {
    Shop: Shop,
    Store: Store
}

build.js

// 这里简单的 copy 了 vue-cli 提供的 build 代码
let webpackConfig = require('./webpack.config')

let rm = require('rimraf')
let path = require('path')
let webpack = require('webpack')
let util = require('util')

const compileCallback = (er, stats) => {
    if (er) throw er
    stats = util.isArray(stats.stats) ? stats.stats : [stats]
    stats.forEach((item) => {
        process.stdout.write(item.toString({
            colors: true,
            modules: false,
            children: false,
            chunks: false,
            chunkModules: false
        }) + '\n\n')
    })         

    console.log('Build complete.\n')
}

rm(path.resolve(__dirname, './dist'), err => {
    if (err) throw err
    let compiler = webpack(webpackConfig)
    
    compiler.run(compileCallback)
})

строить планы

1. Загрузить ссылки

Эта часть хорошо реализована

  • Укажите статический адрес файла (или адрес CDN) для простой загрузки через html
  • Предоставьте пакет npm и загрузите его на стороне сервера (поскольку на данный момент такого требования нет, поэтому сначала зависните)

2. Откройте общедоступную переменную

Самый простой способ сделать это -index.jsРигаwindow.SDK = ...

ноwebpackЕсть лучшие решенияoutput.library

outputпараметры в основном используются для настройки правил вывода файла, в то время какoutput.libraryЭтот параметр можно использовать для предоставления файла в качестве переменной, когда вывод должен быть элементом конфигурации для упаковки файла SDK.

Вот еще одинwebpackучебник, чтобы помочь вам, как использоватьlibrary Создать библиотеку

другой вариантoutput.libraryTargetВы можете настроить, как выводить переменные, значение по умолчаниюvar

Кратко объясните значение этих значений

  • var: экспортировать переменную в текущей области
  • assign: экспортировать переменную как глобальную переменную
  • это: экспортируется какthisатрибут этогоthisНе обязательноwindow, в зависимости от того, где находится ссылка на SDK
  • окно: экспортировать какwindowАтрибут, по сути, даже глобальная переменная
  • глобальный: экспортировать какglobalАтрибут , по оценкам, это имя переменной используется чаще. .
  • commonjs: экспортировать какexportsАтрибут экспортируемого формата можно найти вCommonJSупоминается в среде
  • commonjs2: назначитьmodule.exports, также может быть использован вCommonJSокружающая обстановка
  • amd: подвергается воздействиюAMDмодуль
  • umd: представлен как формат, доступный для всех модулей
  • JSONP: пакет кjsonpупаковочная тара, то естьFunction

Итак, давайте немного изменим егоwebpack.config.jsкод

module.exports = {
    ...
    output: {
        path: './dist',
        filename: '[name].js',
        library: 'SDK',
        libraryTarget: "umd"
    }
    ...
}

3. Доступен в двух версиях

Просто напишите дваbuildскрипты, упакованные как сжатый и несжатый код соответственно, ноwebpackЕго также можно экспортировать как несколько конфигураций (это также обнаруживаетwebpackкак умножитьoutputнастроить разные параметры)

Итак, нашwebpack.config.jsКод изменен на

module.exports = [
  // 未压缩版
  {
        entry: {
            'sdk': './src/index.js'
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: '[name].js',
            library: 'SDK',
            libraryTarget: "umd"
        }
  },

  // 压缩版
  {
        entry: {
            'sdk.min': './src/index.js'
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: '[name].js',
            library: 'SDK',
            libraryTarget: "umd"
        },
        plugins: [
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                },
                sourceMap: true
            })
        ]
  }
]

Результат после упаковки показан на следующем рисунке

4. Обеспечить индивидуальную версию

Это относительно просто, вы можете сделать несколько конфигураций так же, как предыдущую, или вы можете простоentryнаписать несколько записей в

webpack.config.jsКод изменен на

module.exports = [
    {
        entry: {
            'sdk': './src/index.js',
            'custom': './src/custom.js'
        }
        ...
    },
    ...
]

5. Внутренняя реализация через ссылку на модуль

Это уже не многословно... После ряда настроек, не говоря уже о модулях, ES6 может быть добавлен для вас, но следует отметить, что если вы внедритеbabelИли другие библиотеки, упакованныеSDKФайл очень большой, даже простая ссылка наwebpack-mergeувеличит ёмкость на 50К, так что лучше писать родным способом, если надоajaxПросто инкапсулируйте другие функции и по возможности не ссылайтесь на другие библиотеки.Если вы считаете, что размер файла слишком велик, вы можете использоватьwebpack-bundle-analyzerАнализировать распределение размеров файлов и наличие повторяющихся ссылок

Эпилог

Несмотря на то, что это небольшой проект, его следует рассматривать комплексно на начальном этапе.Хотя текущий проект небольшой, неясно, во что он вырастет в будущем.Некоторые люди могут сказать, что такой простой проект должен быть инкапсулирован с замыкание и выставили два интерфейса.,зачем так усложнять,но если потом нужно добавить новые интерфейсы,если нужно предоставить два sdks,каждый с разными интерфейсами,и некоторые одинаковые интерфейсы,если рефакторить в это время , будет ли это правильно?Онлайн имеет большое влияние? Сколько тестов требуется? Это незаметно добавляет нам много затрат и неопределенности.

Я надеюсь, что эта относительно простая статья поможет вам в создании проекта SDK~