【问题标题】:Calling webpacked code from outside (HTML script tag)从外部调用 webpacked 代码(HTML 脚本标签)
【发布时间】:2025-12-09 10:25:02
【问题描述】:

假设我有这样的课程(用打字稿编写),我将它与 webpack 捆绑到 bundle.js

export class EntryPoint {
    static run() {
        ...
    }
}

在我的 index.html 中,我将包含捆绑包,但我也想调用该静态方法。

<script src="build/bundle.js"></script>
<script>
    window.onload = function() {
        EntryPoint.run();
    }
</script>

但是,在这种情况下,EntryPoint 是未定义的。那我如何从另一个脚本调用捆绑的 javascript?

添加Webpack config file

【问题讨论】:

  • 请添加您的 webpack 配置。我相信您的 onload 方法中缺少类似于 var EntryPoint = require('EntryPoint') 的内容。
  • @MartinVseticka 我已经添加了我的配置。确实像require 这样的东西可能是必要的,但与下面的导入相同,它说require is not defined。我想要做的是使用来自普通 javascript 的捆绑内容,我不需要再次使用一些框架来使用require 吗?但我试图避免这种情况。希望这是有道理的。

标签: javascript html typescript webpack


【解决方案1】:

我花了很长时间才弄明白,因为接受的答案对我不起作用。只需确保函数名称与配置中的库相同,并且它与指定的配置捆绑在一起 -- npx webpack --config webpack.config.js --mode=development -- 希望这可以节省人们几个小时。

index.js(要捆绑的功能)>>

function EntryPoint() {
    console.log('called from bundle');
}

module.exports = EntryPoint;

webpack.config.js >>

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
        libraryTarget: 'var',
        library: 'EntryPoint'
    },
};

start.html(调用捆绑函数的地方)>>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Azure SDK Storage Example</title>
    <script type="text/javascript" src="./dist/main.js"></script>
  </head>
  <body>
      <h1>Azure SDK Storage Example</h1>
  </body>
</html>

<script>
 EntryPoint();
</script>

【讨论】:

    【解决方案2】:

    也许这是我的一些冒名顶替综合症,但我认为“真正的”编码人员会对我的回答感到畏缩。无论如何,我发现这个解决方案最适合我在业余爱好项目上的时间务实:

    从以下位置更改您的 JS 函数声明:

    function renderValue(value) {
    

    到:

    global.renderValue = function(value) {
    

    当然,你会想要require('path/to/your_custom_js'),就像你想要任何文件一样。

    我在这里找到了这个答案: https://www.fastruby.io/blog/rails/webpack/from-sprockets-to-webpacker.html

    【讨论】:

      【解决方案3】:

      WEBPACK.CONFIG.JS

      1.使用 UMD

      module.exports={
                  mode:'development',
                  entry:'./yourentry.js',
                  output:{
                      path:path.resolve(__dirname,"dist"),
                      filename:'main.js',
                      publicPath:'/dist/',
                      libraryTarget:'umd', 
                      library:'rstate',
                      umdNamedDefine: true,
                      libraryExport: 'default' 
                  }
          }
      

      index.html

      <script src="dist/main.js"></script>
      <script>
        window.onload = function () {
        rstate()=>{}
      </script>
      

      main.js

      export default function rstate(){
      console.log("i called from html")
      }
      

      2.使用 VAR

      module.exports={
                  mode:'development',
                  entry:'./yourentry.js',
                  output:{
                      path:path.resolve(__dirname,"dist"),
                      filename:'main.js',
                      publicPath:'/dist/',
                      libraryTarget:'var', 
                      library: 'EntryPoint'
                  }
          }
      

      index.html

      <script>
        window.onload = function () {
        EntryPoint.rstate()=>{}
      </script>
      

      main.js

      module.exports={
          rstate=function(){
              console.log("hi module")
          }
      }
      

      3.使用 AMD 作为我们使用 like 的库(对于那些想要制作 lib 的人)

      define(['jquery', './aux-lib.js'], function ($) { ..(1).. });
      

      【讨论】:

        【解决方案4】:

        到目前为止,许多答案都有效,只需要澄清 Webpack 将不会识别库,直到它在声明后构建。 您应该在创建库后立即使用npm run build, 在继续与npm start 合作之前。

        至少对我来说是这样,只使用 webpack。

        【讨论】:

          【解决方案5】:

          我遇到了类似的挑战,我想为旅程中的多个页面创建一个捆绑包,并希望每个页面都有自己的代码入口点,并且每个页面都没有单独的捆绑包。

          这是我的方法,它与 Kurt Williams 非常相似,但角度略有不同,同样没有更改 webpack 配置:

          JourneyMaster.js

          import { getViewData } from './modules/common';
          import { VIEW_DATA_API_URL } from './modules/constants';
          import { createLandingPage, createAnotherPage } from './modules/components/pageBuilder';
          
          window.landingPageInit = () => {
              getViewData(VIEW_DATA_API_URL).then(viewData => {
                  createLandingPage(viewData);
              });
          };
          
          window.anotherPageInit = () => {
              getViewData(VIEW_DATA_API_URL).then(viewData => {
                  createAnotherPage(viewData);
              });
          };
          
          // I appreciate the above could be one liners,
          // but readable at a glance is important to me
          

          然后是我在html页面末尾如何调用这些方法的示例:

          <script src="/js/JourneyMaster.js"></script>
          <script>window.landingPageInit();</script>
          

          【讨论】:

            【解决方案6】:

            您似乎想将 webpack 包公开为 library。您可以配置 webpack 以在您自己的变量中的全局上下文中公开您的库,例如 EntryPoint

            我不知道 TypeScript,所以该示例使用纯 JavaScript。但这里重要的部分是 webpack 配置文件,特别是 output 部分:

            webpack.config.js

            module.exports = {
              entry: './index.js',
              output: {
                path: './lib',
                filename: 'yourlib.js',
                libraryTarget: 'var',
                library: 'EntryPoint'
              }
            };
            

            index.js

            module.exports = {
              run: function () {
                console.log('run from library');
              }
            };
            

            然后您将能够像您期望的那样访问您的库方法:

            <script src="lib/yourlib.js"></script>
            <script>
              window.onload = function () {
                EntryPoint.run();
              };
            </script>
            

            用实际代码检查gist

            【讨论】:

            • 我们有多个入口点,所以在输出部分,我改为library: ["GlobalAccess", "[name]"],。然后使 var 成为具有每个入口点成员的对象:GlobalAccess.EntryPointFoo、GlobalAccess.EntryPointBar 等。
            • 这适用于nam run build,但不适用于使用webpack-dev-server 的开发环境。我导出的 EntryPoint 是一个空对象。有什么想法吗?
            • entry: { page1: [ 'module1.js', 'module2.js' ], page2: 'module3.js' } @JohnHatton 建议似乎不起作用的情况.我可以访问 page1.module2,但不能访问 page1.module1。好像只取最后一个。
            • 按照步骤,更改配置,重建它,但仍然未捕获 ReferenceError: EntryPoint is not defined
            • 通过将 index.js 从 module.exports = ... 更改为 export function run() {},我得到了一个在 babel + webpack v3.10.0 中工作的类似示例
            【解决方案7】:

            在我的情况下,我可以通过在创建函数时将函数写入窗口来从另一个脚本的捆绑 JavaScript 中调用函数。

            // In the bundled script:
            function foo() {
                var modal = document.createElement('div');
            }
            // Bind to the window
            window.foo = foo;
            // Then, in the other script where I want to reference the bundled function I just call it as a normal function
            <button onClick="window.foo()">Click Me</button>
            

            我无法使用 Babel,所以这对我有用。

            【讨论】:

            • 这是一个非常简洁的解决方案。
            【解决方案8】:

            App.ts:

            namespace mytypescript.Pages {
            
                    export class Manage {
            
                 public Initialise() {
                 $("#btnNewActivity").click(() => {
                                alert("sdc'");
                            });
                    }
                }
            }
            

            mypage.html:

             <input class="button" type="button" id="btnNewActivity" value="Register New Activity" />
            
             <script type="text/javascript">
                var page = new mytypescript.Pages.Manage();
                page.Initialise();
            </script>
            

            【讨论】:

              【解决方案9】:

              我只需使用我从 main/index.js 文件中调用的 import 语句,就可以在没有任何进一步的 webpack.config.js 修改的情况下使其工作:

              import EntryPoint from './EntryPoint.js';
              window.EntryPoint = EntryPoint;
              

              作为参考,这是我的weback.config.js 文件。

              最初我尝试使用require 完成相同的操作,但是它将模块包装器分配给window.EntryPoint,而不是实际的类。

              【讨论】:

              • 没有 es6 有机会吗?否则我会得到Uncaught SyntaxError: Unexpected token import。或者您的index.js 是否也捆绑在一起(我确实将其视为入口点,但不确定)?
              • 是的,index.js 也被捆绑在一起——这就是我包含导入语句的地方
              • 你看,我正在尝试访问从不属于捆绑包的脚本捆绑的东西。就像捆绑包是一个库一样,我会尝试从外部访问它的方法。这可能吗?
              • 这个解决方案真的很简单,我为自己没有在问题出现时立即考虑它而感到羞耻。
              • 我被这个问题困扰了好几个小时。只是要将脚本移动到我的包中,但这会导致更多问题。感谢您的简单回答!