Я сам пережил эту боль. Webpack и Browserify могут сделать это, но я не большой поклонник того, как он это делает. Вы действительно правы - вам нужно заранее знать, что можно / нужно загружать.
Я использую Go и GopherJS в моей текущей установке, но моя предыдущая использовала NodeJS, SystemJS и RollupJS , и я до сих пор использую компоненты SystemJS и RollupJS.
Core Bundle
Для объединения вы должны подумать заранее, лично я связываю основные компоненты и обычно называю это core.bundle.js. В своих проектах я помещаю все компоненты на стороне клиента в собственную папку jslib:
Стандартная схема проекта
Я использую TypeScript, поэтому в ./src/index.ts я ссылаюсь на мои основные библиотеки ..:
//@ts-ignore
import * as jquery from "jquery";
import * as popper from "popper.js"
import * as bootstrap from "../vendor/bootstrap/index.js"
import * as backbone from "backbone"
import * as lodash from "lodash"
//@ts-ignore
window.jquery = window.jQuery = window.$ = jquery;
//@ts-ignore
window.popper = popper;
//@ts-ignore
window.bootstrap = bootstrap;
//@ts-ignore
window.Backbone = backbone;
//@ts-ignore
window._ = window.lodash = lodash;
Извиняюсь за многословие, но GopherJS может смешно нуждаться в вещах в определенных местах - но по крайней мере все настроено на объекте окна, который должен быть там.
Тогда у нас есть динамический загрузчик в том же файле:
import * as SystemJS from 'systemjs';
import * as Promise from "bluebird";
export class DynamicModuleManager {
constructor() {
//load up the main package and initialise SystemJS for use
SystemJS.config({
baseURL: '/_pkg', //your dynamic requires will use this folder for the root
meta: { '*': { scriptLoad: true } }
});
}
public init() {
//Register the modules you have already loaded!
//@ts-ignore
SystemJS.set('lodash', SystemJS.newModule({
//@ts-ignore
"default": window.lodash
}));
//@ts-ignore
SystemJS.set('jquery', SystemJS.newModule({
//@ts-ignore
"default": window.$
}));
//Optionally add some shim/fake modules to allow NodeJS stuff to be used if needed
//@ts-ignore
SystemJS.set('child_process', SystemJS.newModule({
ChildProcess: {}
}));
}
public import(moduleId:string) {
return SystemJS.import(moduleId).then((m) => {
console.log(`Loading Module: ${moduleId}`);
//m is the module object just like you had "required" it
return m
});
}
}
Если вы используете машинопись, мой tsconfig будет таким для основного пакета:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es2015", "dom"],
"baseUrl": "./src/",
"outDir": "./build/",
"inlineSourceMap": true,
"paths": {
"*": [
"./node_modules/*"
]
}
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*"
]
}
И тогда конфиг накопления выглядит так:
// rollup.config.js
import builtins from 'rollup-plugin-node-builtins';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
export default {
input: './build/index.js',
output: {
file: '../assets/js/core.bundle.js',
format: 'cjs'
},
name: 'core_bundle',
plugins: [
json(),
builtins(),
nodeResolve(),
commonjs(),
]
}
Я не использую плагин rollup-typcript, потому что он вызвал у меня проблему, так что это 3-этапная сборка:
$ cd ~/your_web_project/jslib
$ npm init && npm install --save jquery... [OTHER DEPS]
## When you clone just make sure to do npm install
$ tsc -p tsconfig.json
## if you are running typescript remember to install globally
$ rollup -c
## again install globally
Теперь у вас будет ~ / your_web_project / assets / js / core.bundle.js
Субмодули
Так что теперь вы можете создавать другие модули / чанки. Для вышеупомянутой конфигурации вам нужно иметь их в директории, которую обслуживает ваш любимый сервер, или из маршрута внутри узла, например: GET / _pkg /: имя_модуля -> ~ / your_web_project / resources / _pkg /: имя_модуля.js
В ваших модулях все, что вам нужно сделать, - это установить другую папку jslib, примерно такую же, но на этот раз расскажите rollupjs о ваших внешних пакетах ...
Динамически загружаемая среда VSCode / Monaco для структуры папок Golang
// rollup.config.js
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import json from 'rollup-plugin-json';
import alias from 'rollup-plugin-alias';
import babel from 'rollup-plugin-babel';
import * as filepath from "path"
//export an array of webpack configs for multiple modules..
export default [
{
input: './build/index.js',
external : ["lodash", "jquery"], //make sure to make the module aware of anything external otherwise it will get bundled!
output: {
file: '../resources/devide.go.js',
format: 'cjs',
},
plugins: [
nodeResolve({
module: true,
jsnext: true,
extensions: [ '.js', '.json' ]
}),
commonjs(),
alias({
'golangcli': filepath.resolve(__dirname, 'build/golangcli/client'),
'vscode': require.resolve('monaco-languageclient/lib/vscode-compatibility')
}),
json(),
postcss({
plugins: [] //you can even embed CSS in your sources and have it load here...
}),
babel({
"presets": ["@babel/preset-env"],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
})
]
}
];
Приведенный выше пример немного экстремален, так как я использую Typescript и Babel до объединения с Rollup.
Цконфиг тоже нуждается в небольших изменениях:
{
"compilerOptions": {
"noImplicitAny": false,
"module": "es2015",
"target": "es2015",
"lib": ["es2015", "dom"],
"baseUrl": "./src/",
"outDir": "./build/",
"inlineSourceMap": false,
"moduleResolution": "node",
"skipLibCheck": true,
"paths": {
"*": [
"./node_modules/*"
]
}
},
"include": [
"src/**/*"
]
}
Это приведет к правильному дрожанию дерева, когда источник сворачивается, и гарантирует, что импортируется только то, что действительно нужно. Важно, когда полезная нагрузка Монако превышает 10 МБ!
Свертывание - отличный набор, я даже использую его для свертывания целых серверных кодовых баз, чтобы их можно было копировать и запускать зависимости и все без проблем (если у вас есть двоичный файл узла), и он работает очень хорошо с настройками Golang, Buffalo, GopherJS, которые у меня есть.
TL; DR
Вышеупомянутая проблема - это то, с чем я боролся долгое время и чувствовал, что это достойно моего первого в истории Ответа на SO. Без сомнения, в указанном решении есть дыры, но, надеюсь, оно кого-то вдохновит!