Есть ли в webpack что-то вроде libraryTarget из «function»? - PullRequest
0 голосов
/ 08 мая 2018

Мне бы хотелось, чтобы моя библиотека, скомпилированная в веб-пакете, была возвращаемым значением функции.

Webpack позволит мне скомпилировать вывод и назначить результат переменной , установив libraryTarget в моем файле конфигурации на var, что даст мне что-то вроде этого:

var MyLibrary = function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,expo...;

Если я просто включу этот выходной файл, как есть, в свою веб-страницу, я получу window.MyLibrary, что не совсем то, что я хотел, а уже ближе.

У меня есть продвинутый вариант использования (тот, который трудно полностью объяснить, не написав об этом книгу). Достаточно сказать, что я бы предпочел «инициализировать» библиотеку с помощью функции, например:

function init(){
    return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,expo...;
}

Я надеялся найти вариант libraryTarget по этим направлениям, но, увы, в документах его нет.

Должен ли я использовать другие инструменты сборки, чтобы объединить мой выходной файл в другой файл, например, в шаблон? Или в веб-пакете есть функция, которую я пропустил? Возможно, этот результат достижим благодаря использованию нескольких других расширенных функций в концерте? Я не против плагинов, но, очевидно, я бы предпочел нативную функциональность.


Вот более подробный пример того, чего я хотел бы достичь.

Текущий код

utils.js

let d = new Date();

export default {
    getInitDateTime(id){
        return d;
    }
};

lib.js

import utils from "./utils.js";

export let lib = ({
    test: function(){
        return utils.getInitDateTime();
    }
});

webpack.config.js

const path = require('path');

module.exports = {
    mode: 'production',
    entry: './lib.js',
    output: {
        filename: 'bundle.js',
        libraryTarget: 'var',
        libraryExport: 'lib',
        library: 'mylib',
    }
};

bundle.js (скомпилировано)

var mylib=function(e){var t={};function n(r){if(t[r])return t[r].exports;var u=t[r]={i:r,l:!1,exports:{}};return e[r].call(u.exports,u,u.exports,n),u.l=!0,u.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);let r=new Date;var u={getInitDateTime:e=>r};n.d(t,"lib",function(){return o});let o={test:function(){return u.getInitDateTime()}}}]).lib;

index.html

<html>
    <head></head>
    <body>
        <button id="btn">Click Me</button>
        <div id="root"></div>
        <script src="dist/bundle.js"></script>
        <script>
            var btn = document.getElementById('btn');
            var root = document.getElementById('root');

            btn.onclick = function(){
                var div = document.createElement('div');
                div.innerHTML = 'Test: ' + mylib.test();
                root.appendChild( div );
            }
        </script>
    </body>
</html>

Если вы нажмете кнопку три раза, вы получите что-то вроде:

Тест: вторник, 08 мая 2018 10:28:41 GMT-0400 (EDT)
Тест: вторник, 08 мая 2018 10:28:41 GMT-0400 (EDT)
Тест: вторник, 08 мая 2018 10:28:41 GMT-0400 (EDT)

Желаемый результат

Вот как я хотел бы использовать мою библиотеку в index.html:

<html>
    <head></head>
    <body>
        <button id="btn">Click Me</button>
        <div id="root"></div>
        <script src="dist/bundle.js"></script>
        <script>
            var btn = document.getElementById('btn');
            var root = document.getElementById('root');

            btn.onclick = function(){

                // ******************************************
                // Create a new instance of the library:
                var mylib = initmylib();
                // ******************************************

                var div = document.createElement('div');
                div.innerHTML = 'Test: ' + mylib.test();
                root.appendChild( div );
            }
        </script>
    </body>
</html>

Итак, если я нажму кнопку три раза, я получу что-то вроде:

Тест: вторник, 08 мая 2018 10:40:41 GMT-0400 (EDT)
Тест: вторник, 08 мая 2018 10:40:42 GMT-0400 (EDT)
Тест: вторник, 08 мая 2018 10:40:43 GMT-0400 (EDT)

Я уже могу сделать это, вручную изменив мой bundle.js следующим образом:

function initmylib(){
    return function(e){var t={};function n(r){if(t[r])return t[r].exports;var u=t[r]={i:r,l:!1,exports:{}};return e[r].call(u.exports,u,u.exports,n),u.l=!0,u.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);let r=new Date;var u={getInitDateTime:e=>r};n.d(t,"lib",function(){return o});let o={test:function(e,t){return u.getInitDateTime()}}}]).lib;
}

Но это требует либо ручной модификации, либо дополнительных шагов сборки. Я хотел бы знать, может ли webpack сделать что-то подобное самостоятельно.

Да, этот MCVE тривиален ... Моя настоящая библиотека - нет.

Очевидно, что эта конкретная библиотека тривиальна, и я мог бы легко изменить ее поведение на желаемое. Проблема в том, что моей настоящей библиотеке около 5-6 лет, она содержит сотни тысяч строк кода, распределенных по сотням файлов, и активно используется в существующем продукте. Я пытаюсь перенести его медленно и хочу использовать для этого веб-пакет. Рефакторинг всего авансом будет слишком трудоемким. Если бы я мог просто обернуть пакет в функцию (как показано), это очень быстро решило бы множество проблем.

Я могу использовать дополнительные этапы сборки для достижения своей цели ... Я просто хочу знать, может ли веб-пакет сделать это для меня.

1 Ответ

0 голосов
/ 08 мая 2018

Я не думаю, что webpack может автоматически вызвать функцию для вас. При первом просмотре веб-пакета ваш модуль получает экспорт и кэширует его. При последующем импорте возвращается из кэша.

Но вы можете попробовать что-то вроде этого:

  export default function createLibraryInstance () {
    let myPrivateValue = 1;

    return {
      getValue: function () {
        return myPrivateValue;
      }
    }
  }

затем в конфиге webpack:

  {
    output: {
      library: 'createLibraryInstance',
      libraryTarget: 'var'
    }
  }

используйте это так:

  let myInstance = window.createLibraryInstance();
...