การเรียกโค้ด webpacked จากภายนอก (แท็กสคริปต์ HTML)


130

สมมติว่าฉันมีคลาสเช่นนี้ (เขียนด้วย typescript) และฉันรวมกับ webpack ไว้ในbundle.jsไฟล์.

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

ใน index.html ของฉันฉันจะรวมบันเดิลไว้ แต่ฉันก็อยากจะเรียกว่าวิธีการคงที่

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

อย่างไรก็ตามEntryPointไม่ได้กำหนดไว้ในกรณีนี้ ฉันจะเรียกจาวาสคริปต์ที่รวมมาจากสคริปต์อื่นได้อย่างไร

เพิ่ม : ไฟล์กำหนดค่าWebpack


โปรดเพิ่มการกำหนดค่า webpack ของคุณ ฉันเชื่อว่ามีบางอย่างที่var EntryPoint = require('EntryPoint')ขาดหายไปในonloadวิธีการของคุณ
Martin Vseticka

2
@MartinVseticka ฉันได้เพิ่ม config ของฉันแล้ว อันที่จริงบางอย่างเช่นrequireอาจจะจำเป็น require is not definedแต่เช่นเดียวกับการนำเข้าด้านล่างก็กล่าวว่า สิ่งที่ฉันกำลังพยายามทำคือการใช้เนื้อหาที่รวมจากจาวาสคริปต์ธรรมดาฉันจะไม่ต้องการเฟรมเวิร์กเพื่อใช้อีกrequireหรือ แต่ฉันพยายามหลีกเลี่ยงสิ่งนั้น หวังว่ามันจะสมเหตุสมผล
Raven

คำตอบ:


147

ดูเหมือนว่าคุณต้องการที่จะเปิดเผยกำ webpack เป็นห้องสมุด คุณสามารถกำหนดค่า 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>

ตรวจสอบส่วนสำคัญด้วยรหัสจริง


20
library: ["GlobalAccess", "[name]"],เรามีคะแนนหลายรายการดังนั้นในส่วนของการส่งออกที่ฉันทำให้มันแทน จากนั้นทำให้ var เป็นวัตถุที่มีสมาชิกสำหรับแต่ละจุดเข้า: GlobalAccess.EntryPointFoo, GlobalAccess.EntryPointBar และอื่น ๆ
John Hatton

3
งานนี้nam run buildแต่ไม่ทำงานใน dev env webpack-dev-serverใช้ EntryPoint ที่ส่งออกของฉันเป็นวัตถุว่างเปล่า ความคิดใด ๆ ?
nkint

1
สิ่งที่เกี่ยวกับสถานการณ์ที่รายการ: {page1: ['module1.js', 'module2.js'], page2: 'module3.js'} คำแนะนำ @JohnHatton ดูเหมือนจะใช้ไม่ได้ ฉันสามารถเข้าถึง page1.module2 ได้ แต่ไม่สามารถเข้าถึง page1.module1 ดูเหมือนว่าจะใช้เวลาเพียงคนสุดท้าย
sheamus

1
ทำตามขั้นตอนเปลี่ยน config สร้างใหม่ แต่ยังไม่ได้รับ ReferenceError: EntryPoint ไม่ได้กำหนด
user889030

2
ฉันได้รับตัวอย่างที่คล้ายกันในการทำงานใน babel + webpack v3.10.0 โดยเปลี่ยน index.js เป็นexport function run() {}frommodule.exports = ...
dworvos

55

ฉันจัดการเพื่อให้มันใช้งานได้โดยไม่ต้องwebpack.config.jsแก้ไขเพิ่มเติมโดยใช้importคำสั่งที่ฉันเรียกจากไฟล์ main / index.js ของฉัน:

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

ใส่คำอธิบายภาพที่นี่

สำหรับการอ้างอิงนี่คือweback.config.jsไฟล์ของฉัน

ในตอนแรกฉันพยายามทำสิ่งเดียวกันโดยใช้requireแต่มันกำหนดให้โมดูลห่อหุ้มwindow.EntryPointซึ่งตรงข้ามกับคลาสจริง


3
มีโอกาสทำสิ่งนี้โดยไม่ใช้ es6 หรือไม่? Uncaught SyntaxError: Unexpected token importมิฉะนั้นฉันจะได้รับ หรือของคุณindex.jsรวมอยู่ด้วย (ฉันเห็นว่าเป็นจุดเริ่มต้น แต่ไม่แน่ใจ)
Raven

ใช่แล้ว index.js ก็รวมอยู่ด้วยเช่นกันซึ่งเป็นที่ที่ฉันได้รวมคำสั่งนำเข้า
แมตต์

3
คุณเห็นไหมว่าฉันกำลังพยายามเข้าถึงบางสิ่งที่รวมมาจากสคริปต์ที่ไม่ได้อยู่ในบันเดิล เช่นเดียวกับบันเดิลเป็นไลบรารีและฉันจะพยายามเข้าถึงวิธีการจากภายนอก เป็นไปได้หรือไม่
Raven

4
วิธีแก้ปัญหานี้ง่ายมากและฉันก็ละอายใจตัวเองที่ไม่ได้คิดถึงมันทันทีที่เกิดปัญหาขึ้น
cav_dan

1
ฉันติดปัญหานี้มาหลายชั่วโมงแล้ว กำลังจะย้ายสคริปต์ไปไว้ในบันเดิลของฉัน แต่นั่นจะทำให้เกิดปัญหามากขึ้น ขอบคุณสำหรับคำตอบง่ายๆ !!
Stephen Agwu

14

ในสถานการณ์ของฉันฉันสามารถเรียกใช้ฟังก์ชันจากภายใน 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 ได้ดังนั้นสิ่งนี้จึงใช้ได้กับฉัน


นี่เป็นวิธีแก้ปัญหาที่เรียบร้อยมาก
Teoman shipahi

1

ฉันมีความท้าทายที่คล้ายกันฉันต้องการสร้างชุดสำหรับหลาย ๆ หน้าภายในการเดินทางและต้องการให้แต่ละหน้ามีจุดเข้าสู่โค้ดเป็นของตัวเองและไม่มีกลุ่มแยกต่างหากสำหรับแต่ละหน้า

นี่คือแนวทางของฉันซึ่งคล้ายกับ 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>

0

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 เป็นไลบรารีที่เราใช้เช่น (สำหรับผู้ที่ต้องการสร้าง lib)

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

-4

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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.