2016-05-15 24 views
9

Tôi muốn có thể gói ứng dụng React của mình với Webpack sao cho các bản sao được phân phối vào CDN có thể được cung cấp, gọi và khởi tạo với một loạt cấu hình có liên quan đến máy khách.Viết plugin Javascript nhúng với React & Webpack

Sau khi đọc thisthis, Tôi đang thiết lập tập tin nhập webpack của tôi như sau:

// ... React requires etc. 

(() => { 
    this.MyApp = (config) => { 
    // some constructor code here 
    } 

    MyApp.prototype.init =() => { 
    ReactDOM.render(<MyReactApp config={MyApp.config} />, someSelector); 
    } 
})(); 

Ý tưởng được rằng trong ứng dụng của tôi, tôi có thể làm điều gì đó như sau:

<script src="./bundle.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    MyApp.init({ 
    some: "config" 
    }); 
</script> 

Và chức năng MyApp#init của tôi sẽ hiển thị ứng dụng React của tôi bên trong một số vùng chứa trên máy khách.

Tôi có đang nghĩ về điều này đúng không? Có cách nào đơn giản hơn hoặc hiệu quả hơn để thực hiện việc này không?

Lỗi của tôi là Uncaught TypeError: Cannot set property 'MyApp' of undefined, kể từ this bên trong IIFE là undefined. Tôi thực sự muốn hiểu cả lý do tại sao điều này xảy ra và lời khuyên về cách khắc phục.

Cảm ơn trước!

Trả lời

14

Vì vậy, tôi loại tìm thấy một giải pháp này, như mô tả here

Nếu tôi thay đổi tập tin của tôi webpack.config.js để thêm các thuộc tính sau cho đối tượng output, tức là

var config = { 
    // ... 
    output: { 
    // ... 
    library: 'MyApp', 
    libraryTarget: 'umd', 
    umdNamedDefine: true, 
    } 
} 

này quy định các tập tin tôi đang kết hợp với webpack dưới dạng mô-đun UMD, vì vậy nếu tôi có chức năng trong tệp đó và xuất ...

export const init = (config) => { 
    ReactDOM.render(<MyReactApp config={config} />, someSelector); 
} 

Tôi có thể, sau đó, trong khách hàng của tôi, làm như sau.

<script src="./bundle.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    MyApp.init({ 
    some: "config" 
    }); 
</script> 

Và ứng dụng React của tôi hiển thị.

Nếu có ai đó nghĩ rằng đây là cách thức hoạt động không tốt, tôi rất muốn nghe nó!

+0

Hi, mattsch. Đây là một giải pháp tốt đẹp. Câu hỏi duy nhất tôi có là làm thế nào tôi có thể kiểm tra tiện ích đó được tích hợp trên trang web của khách hàng.Vì vậy, hãy nói rằng có một ứng dụng và xây dựng một widget. Tôi muốn kiểm tra trong ứng dụng mà một số người dùng (bằng id hoặc tên máy) nhúng một widget trên trang web của họ. –

+0

@To_wave Tôi đoán là một phần của hàm 'init', bạn có thể ping một yêu cầu quay lại máy chủ của bạn với các chi tiết của máy khách - điều đó có thể hoạt động? – mattsch

+0

Tôi nghĩ về điều đó, nhưng giải pháp đó không cho phép tôi kiểm tra xem khách hàng đã xóa một widget từ trang web của họ. Vì vậy, với callback tôi có thể kiểm tra duy nhất là widget tích hợp, nhưng không loại bỏ –

0

Bạn có khu vực xung quanh lớp học của mình.

MyApp cần được xuất hoặc đính kèm với đối tượng cửa sổ chung trước khi bạn có thể gọi nó như thế.

Trong trường hợp của bạn, bạn đang thực sự không gọi MyApp.init() nhưng bạn đang gọi window.MyApp.init(), nhưng cửa sổ đối tượng toàn cầu không có đối tượng MyApp đính kèm với nó.

// ... Simple attaching MyApp to the window (as a function) 
window.MyApp = (config) => { 
    ... 
} 

// ... Using class and export 
class MyApp { 
    constructor(config){...} 
} 
export default MyApp 

// or simply attach to the window 
window.MyApp = MyApp 

Tôi muốn tạo mô-đun lớp và xuất bằng cách xuất. Sau đó, tạo một tệp khác chỉ để đính kèm vào cửa sổ. Vì nó không được coi là thực hành tốt nhất để đính kèm các lớp học vào cửa sổ như thế.

// Import module and attach it to the window 
import MyApp from '.my-app' 
window.MyApp = MyApp 

Bạn có thể tìm kiếm tùy chọn nâng cao của xuất khẩu mô-đun như UMD, AMD ...

Các vấn đề liên quan