将 requirejs 和普通 js 文件合并在一起
Merging requirejs and plain js file together
我正在开发一个小网站,主HTML页面基本上是这样的:
<html lang="en">
<head>
<script src="ace.js" type="text/javascript"><script>
<script src="ext-language_tools.js" type="textjavascript"></script>
<script src="mode-mongo.js" type="text/javascript"></script>
<script src="playground.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
ace.config.setModuleUrl("ace/mode/mongo", "mode-mongo.js")
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
(真人可见here).
以下是未缩小的文件:
前 3 个 js 文件使用 requirejs,第 4 个只是普通的 js
有没有办法将这 4 个文件合并成一个文件,以便在我的 HTML 中有类似的东西?
<html lang="en">
<head>
<script src="bundle.js" type="text/javascript"><script>
<script type="text/javascript">
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
编辑
我的目标是一次加载所有这些 js 代码在单个 HTTP 请求中
您可以require
将它们放在一个 js 文件中并在您的模板中引用它。
像这样:
bundle.js:
require(../ace.js);
// other files
require(../playground.js);
我有点困惑。您说您对前 3 个文件使用 requirejs,但这不是我对如何使用 requirejs 的理解。你通常会有一个主 JavaScript 文件(我们称它为 main.js),你的 HTML 会加载一个 JavaScript 文件,即 require.js 文件,它将指定要加载的 main.js 文件:
<html lang="en">
<head>
<script src="require.js" data-main="main"><script>
<!-- The following does not currently use require.js: -->
<script src="playground.js"><script>
<script>
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
然后在 main.js 中,您将使用 require()
(或 requirejs()
)加载您需要的任何其他脚本 运行。例如:
require(["ace"], function(ace) {
//This function is called when scripts/ace.js is loaded.
//If ace.js calls define(), then this function is not fired until
//ace's dependencies have loaded, and the ace argument will hold
//the module value for "ace".
});
而需要 ace 模块的 window.onload
事件处理程序将移至 main.js[=62= 内部] 文件。
现在,如果您想将 4 个文件捆绑到一个文件中,那么假设您已经安装了 Node.js
,最简单的方法是先使用 requirejs 安装npm:
npm install -g requirejs
下一步安装 uglify:
npm install uglify-js -g
然后在包含您的脚本的目录中创建一个新的 JavaScript 文件 main.js:
require(['ace', 'ext-language-tools', 'mode-mongo', 'playground'], function(ace) {
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
});
};
});
然后从脚本目录执行:
r.js -o name=main out=bundle.js
如果您在 Windows 下 运行,则需要将上面的 r.js
替换为 r.js.cmd
。这应该给你一个单一的、缩小的文件 bundle.js。如果您不想缩小文件,那么:
r.js -o name=main out=bundle.js optimize=none
然后修改您的 HTML 使其看起来像:
<html lang="en">
<head>
<script src="require.js" data-main="bundle"><script>
</head>
<body>
<div class="editor">
</body>
</html>
当然,您的 main.js
:
中不需要 window.onload
事件
require(['ace', 'ext-language-tools', 'mode-mongo', 'playground'], function() {});
然后你的 HTML 变成:
<html lang="en">
<head>
<script src="require.js" data-main="bundle"><script>
<script>
require(['ace'], function(ace) {
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
});
};
});
</script>
</head>
<body>
<div class="editor">
</body>
</html>
@Booboo 的回答大部分是正确的。但我想加上我的 5 美分:
ace.js
在你的回购中,在你的问题中已经捆绑了!它实际上并不使用 requirejs
。一切都已经在里面了。你可以在DevTools中自行查看:只会有一个网络请求。因此,它不适用于 requirejs
s 文档和@Booboo 的回答所建议的设置。
- 为了能够使用
requirejs
的捆绑机制,您需要添加 ace
. 的源
- 也可以,但不一定要使用
r.js
。目前尚不清楚您的目标是什么。但是,如果出于某种原因您只想在 html 中使用一个脚本入口点(不确定为什么需要这个)- <script src="require.js" data-main="main" />
就足够了。
- 再一次,由于您的目标不明确,我建议您不要这样做。
ace
项目中只有 2 个附加文件。其他人是你的,所以只捆绑他们。如果您将代码捆绑到 ace.js
,那么每次您的代码更改时,您的用户将不得不一次又一次地下载 ace.js
的所有知识库,因为浏览器将无法使用它的缓存版本。捆绑包的主要思想(也是 CDN 背后的原因之一)正是关于在长 运行 中最小化请求数量 。如果您担心新用户不会再次光临,因为您的网站在他们第一次访问时花费了更长的时间进行初始化……好吧,也许速度不是您主要关心的问题。此外,浏览器可以有 6 个并行连接,因此 一个 捆绑包实际上会减慢您的网站速度。
这是一个有趣的问题,因为在 JavaScript 和 Web 开发中有许多跨越几个时代和哲学的潜在解决方案。我将讨论最简单和最古老的文件串联,并简要介绍 RequireJS,以及使用专用 Web 捆绑器的更现代的方法。还有一个未说明的潜在假设 为什么 你觉得你需要捆绑它——可能有一些文件加载假设可能不正确,特别是 HTTP/2。
快捷方式
如果您想要快速、简单和老式的东西,您可以将所有 JavaScript 文件组合(串联)在一起。这基本上就是您初始网页中发生的事情:浏览器下载所有 JavaScript 文件并按顺序运行它们。
使用 Unix/Linux/OS X:
连接
cat path/to/ace.js <(echo) \
path/to/ext-language_tools.js <(echo) \
path/to/mode-mongo.js <(echo) \
path/to/playground.js \
> path/to/bundle.js
(如果删除 \
s,则可以将它们全部组合在一行中。如果知道文件以新行结尾,也可以省略 <(echo)
)
或者,您可以手动将文件复制并粘贴到一个大文件中。
RequireJS 方式
值得一提的是 RequireJS 的做事方式,它使用 require
语句,因为这是 ace.js 的开发理念。使用这种理念,文件旨在作为模块保持分离并根据需要加载。其他答案更详细地解释了这种方法,但我要补充一点,捆绑似乎不是使用 RequireJS 的惯用方式——库最初打算(虽然不需要)模块被拆分成不同的文件。
Web Bundler 方式
近年来,人们采用网络打包器(如 webpack、parcel、rollup 等)来管理多个文件和依赖项。这些工具旨在输出一个单一的网络包,并为此提供了许多不错的、可定制的功能。他们可能需要一些工作才能起床 运行,并且需要使用 CommonJS 插件才能使 require
正常工作。例如,请参阅 here 以获取使用 webpack 的 ace。
需要捆绑吗?
根据您的顾虑和情况,捆绑可能不需要是您需要的优化。从历史上看,捆绑被用作最小化网络请求的一种方式,因为网络连接的数量是有限的,有时文件会请求其他文件,从而导致串行加载。 HTTP/2 解决了其中许多问题。只需确保您的网络服务器支持 HTTP/2 并且您正在为该服务器上的所有文件提供服务。有关此的更多信息,。您可能最关心它在实践中的运作方式,因此您可能希望以任何一种方式对其进行基准测试,但您可能不会有太多收获。
我们可以简单地使用 webpack 来得到你想要的东西
module.exports = {
entry: ["./ace.js", "./playground.js" ....],
output: {
filename: "bundle.js"
}
}
可以同时使用require
和source script
,
首先,配置您的webpack.config.js
Webpack Docs
const path = require('path');
const toml = require('toml');
const yaml = require('yamljs');
const json5 = require('json5');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
stats: 'errors-only',
mode: 'development',
entry: './src/index.js',
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 3000,
},
plugins: [
new HtmlWebpackPlugin({
title: 'Artificial Intelligence',
}),
],
output: {
filename: '[contenthash].bundle.js',
path: path.resolve(__dirname, 'public'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.toml$/i,
type: 'json',
parser: {
parse: toml.parse,
},
},
{
test: /\.yaml$/i,
type: 'json',
parser: {
parse: yaml.parse,
},
},
{
test: /\.json5$/i,
type: 'json',
parser: {
parse: json5.parse,
},
},
],
},
};
第二步,require
你需要的文件
// Es5
const x = require('x');
const y = require('y');
// Es6
import * as x from 'x';
import y from 'y';
import { z } from 'z';
使用script tag
代替importing
<html lang="en">
<head>
...
</head>
<body>
<script src="x.js"></script>
<script src="y.js"></script>
<script>
const x = new X();
</script>
</body>
</html>
注意:脚本终究要执行
您也可以 use the scripts
您 imported in the script tag
在您的文件中
App.js
const x = new X();
cosnt y = new Y();
如下列出您不需要的文件
我正在开发一个小网站,主HTML页面基本上是这样的:
<html lang="en">
<head>
<script src="ace.js" type="text/javascript"><script>
<script src="ext-language_tools.js" type="textjavascript"></script>
<script src="mode-mongo.js" type="text/javascript"></script>
<script src="playground.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
ace.config.setModuleUrl("ace/mode/mongo", "mode-mongo.js")
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
(真人可见here).
以下是未缩小的文件:
前 3 个 js 文件使用 requirejs,第 4 个只是普通的 js
有没有办法将这 4 个文件合并成一个文件,以便在我的 HTML 中有类似的东西?
<html lang="en">
<head>
<script src="bundle.js" type="text/javascript"><script>
<script type="text/javascript">
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
编辑
我的目标是一次加载所有这些 js 代码在单个 HTTP 请求中
您可以require
将它们放在一个 js 文件中并在您的模板中引用它。
像这样:
bundle.js:
require(../ace.js);
// other files
require(../playground.js);
我有点困惑。您说您对前 3 个文件使用 requirejs,但这不是我对如何使用 requirejs 的理解。你通常会有一个主 JavaScript 文件(我们称它为 main.js),你的 HTML 会加载一个 JavaScript 文件,即 require.js 文件,它将指定要加载的 main.js 文件:
<html lang="en">
<head>
<script src="require.js" data-main="main"><script>
<!-- The following does not currently use require.js: -->
<script src="playground.js"><script>
<script>
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
})
}
</script>
</head>
<body>
<div class="editor">
</body>
</html>
然后在 main.js 中,您将使用 require()
(或 requirejs()
)加载您需要的任何其他脚本 运行。例如:
require(["ace"], function(ace) {
//This function is called when scripts/ace.js is loaded.
//If ace.js calls define(), then this function is not fired until
//ace's dependencies have loaded, and the ace argument will hold
//the module value for "ace".
});
而需要 ace 模块的 window.onload
事件处理程序将移至 main.js[=62= 内部] 文件。
现在,如果您想将 4 个文件捆绑到一个文件中,那么假设您已经安装了 Node.js
,最简单的方法是先使用 requirejs 安装npm:
npm install -g requirejs
下一步安装 uglify:
npm install uglify-js -g
然后在包含您的脚本的目录中创建一个新的 JavaScript 文件 main.js:
require(['ace', 'ext-language-tools', 'mode-mongo', 'playground'], function(ace) {
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
});
};
});
然后从脚本目录执行:
r.js -o name=main out=bundle.js
如果您在 Windows 下 运行,则需要将上面的 r.js
替换为 r.js.cmd
。这应该给你一个单一的、缩小的文件 bundle.js。如果您不想缩小文件,那么:
r.js -o name=main out=bundle.js optimize=none
然后修改您的 HTML 使其看起来像:
<html lang="en">
<head>
<script src="require.js" data-main="bundle"><script>
</head>
<body>
<div class="editor">
</body>
</html>
当然,您的 main.js
:
window.onload
事件
require(['ace', 'ext-language-tools', 'mode-mongo', 'playground'], function() {});
然后你的 HTML 变成:
<html lang="en">
<head>
<script src="require.js" data-main="bundle"><script>
<script>
require(['ace'], function(ace) {
window.onload = function() {
configEditor = ace.edit(document.getElementById("editor"), {
"mode": "ace/mode/mongo",
"useWorker": false
});
};
});
</script>
</head>
<body>
<div class="editor">
</body>
</html>
@Booboo 的回答大部分是正确的。但我想加上我的 5 美分:
ace.js
在你的回购中,在你的问题中已经捆绑了!它实际上并不使用requirejs
。一切都已经在里面了。你可以在DevTools中自行查看:只会有一个网络请求。因此,它不适用于requirejs
s 文档和@Booboo 的回答所建议的设置。- 为了能够使用
requirejs
的捆绑机制,您需要添加ace
. 的源
- 也可以,但不一定要使用
r.js
。目前尚不清楚您的目标是什么。但是,如果出于某种原因您只想在 html 中使用一个脚本入口点(不确定为什么需要这个)-<script src="require.js" data-main="main" />
就足够了。 - 再一次,由于您的目标不明确,我建议您不要这样做。
ace
项目中只有 2 个附加文件。其他人是你的,所以只捆绑他们。如果您将代码捆绑到ace.js
,那么每次您的代码更改时,您的用户将不得不一次又一次地下载ace.js
的所有知识库,因为浏览器将无法使用它的缓存版本。捆绑包的主要思想(也是 CDN 背后的原因之一)正是关于在长 运行 中最小化请求数量 。如果您担心新用户不会再次光临,因为您的网站在他们第一次访问时花费了更长的时间进行初始化……好吧,也许速度不是您主要关心的问题。此外,浏览器可以有 6 个并行连接,因此 一个 捆绑包实际上会减慢您的网站速度。
这是一个有趣的问题,因为在 JavaScript 和 Web 开发中有许多跨越几个时代和哲学的潜在解决方案。我将讨论最简单和最古老的文件串联,并简要介绍 RequireJS,以及使用专用 Web 捆绑器的更现代的方法。还有一个未说明的潜在假设 为什么 你觉得你需要捆绑它——可能有一些文件加载假设可能不正确,特别是 HTTP/2。
快捷方式
如果您想要快速、简单和老式的东西,您可以将所有 JavaScript 文件组合(串联)在一起。这基本上就是您初始网页中发生的事情:浏览器下载所有 JavaScript 文件并按顺序运行它们。
使用 Unix/Linux/OS X:
连接cat path/to/ace.js <(echo) \
path/to/ext-language_tools.js <(echo) \
path/to/mode-mongo.js <(echo) \
path/to/playground.js \
> path/to/bundle.js
(如果删除 \
s,则可以将它们全部组合在一行中。如果知道文件以新行结尾,也可以省略 <(echo)
)
或者,您可以手动将文件复制并粘贴到一个大文件中。
RequireJS 方式
值得一提的是 RequireJS 的做事方式,它使用 require
语句,因为这是 ace.js 的开发理念。使用这种理念,文件旨在作为模块保持分离并根据需要加载。其他答案更详细地解释了这种方法,但我要补充一点,捆绑似乎不是使用 RequireJS 的惯用方式——库最初打算(虽然不需要)模块被拆分成不同的文件。
Web Bundler 方式
近年来,人们采用网络打包器(如 webpack、parcel、rollup 等)来管理多个文件和依赖项。这些工具旨在输出一个单一的网络包,并为此提供了许多不错的、可定制的功能。他们可能需要一些工作才能起床 运行,并且需要使用 CommonJS 插件才能使 require
正常工作。例如,请参阅 here 以获取使用 webpack 的 ace。
需要捆绑吗?
根据您的顾虑和情况,捆绑可能不需要是您需要的优化。从历史上看,捆绑被用作最小化网络请求的一种方式,因为网络连接的数量是有限的,有时文件会请求其他文件,从而导致串行加载。 HTTP/2 解决了其中许多问题。只需确保您的网络服务器支持 HTTP/2 并且您正在为该服务器上的所有文件提供服务。有关此的更多信息,
我们可以简单地使用 webpack 来得到你想要的东西
module.exports = {
entry: ["./ace.js", "./playground.js" ....],
output: {
filename: "bundle.js"
}
}
可以同时使用require
和source script
,
首先,配置您的webpack.config.js
Webpack Docs
const path = require('path');
const toml = require('toml');
const yaml = require('yamljs');
const json5 = require('json5');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
stats: 'errors-only',
mode: 'development',
entry: './src/index.js',
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 3000,
},
plugins: [
new HtmlWebpackPlugin({
title: 'Artificial Intelligence',
}),
],
output: {
filename: '[contenthash].bundle.js',
path: path.resolve(__dirname, 'public'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.toml$/i,
type: 'json',
parser: {
parse: toml.parse,
},
},
{
test: /\.yaml$/i,
type: 'json',
parser: {
parse: yaml.parse,
},
},
{
test: /\.json5$/i,
type: 'json',
parser: {
parse: json5.parse,
},
},
],
},
};
第二步,require
你需要的文件
// Es5
const x = require('x');
const y = require('y');
// Es6
import * as x from 'x';
import y from 'y';
import { z } from 'z';
使用script tag
代替importing
<html lang="en">
<head>
...
</head>
<body>
<script src="x.js"></script>
<script src="y.js"></script>
<script>
const x = new X();
</script>
</body>
</html>
注意:脚本终究要执行
您也可以 use the scripts
您 imported in the script tag
在您的文件中
App.js
const x = new X();
cosnt y = new Y();
如下列出您不需要的文件