2011-10-20 27 views
21

Giả sử tôi muốn đưa ra một số mã phổ biến giữa các tệp * .clj phía máy khách và phía máy chủ * .clj của tôi, ví dụ: cấu trúc dữ liệu khác nhau và các hoạt động phổ biến, tôi có thể làm điều đó không? Liệu nó có ý nghĩa để làm điều đó?Chia sẻ mã giữa máy chủ và ứng dụng khách trong Clojurescript/Clojure

+2

Nó thực sự có ý nghĩa, giống như trong GWT bạn cũng có thể chia sẻ mã Java trên máy chủ và trên máy khách. Sẽ rất tuyệt khi nghe câu trả lời về điều này! –

+0

cách duy nhất tôi có thể nghĩ ngay bây giờ là đặt mã chia sẻ trong không gian tên máy chủ và cấu trúc thư mục, sau đó thêm dòng vào mã biên dịch của bạn để sao chép các tệp vào thư mục nguồn của máy khách, đổi tên thành * .cljs - vì clojurescript trình biên dịch chỉ tìm kiếm các tệp có tên .cljs – Hendekagon

Trả lời

13

Cập nhật: tính từ clojure 1.7, hãy kiểm tra Clojure reader conditionals or cljc. Tôi đã sử dụng cljc với thành công lớn để chia sẻ rất nhiều mã giữa máy chủ và trình duyệt rất dễ dàng.

Câu hỏi hay! Tôi đã suy nghĩ rất nhiều về điều này cũng như gần đây và đã viết một vài ứng dụng để thử nghiệm.

Dưới đây là danh sách của tôi về những loại điều bạn có thể muốn chia sẻ và ưu/nhược điểm của mỗi:

  • Hầu hết các khách hàng của tôi cljs file có chứa mã mà thao túng các dom. Vì vậy, nó sẽ không có ý nghĩa để chia sẻ bất kỳ điều đó với máy chủ
  • Hầu hết các công cụ bên giao dịch với hệ thống tập tin và các cuộc gọi cơ sở dữ liệu. Tôi cho rằng bạn có thể muốn gọi cơ sở dữ liệu từ máy khách (đặc biệt là nếu bạn đang sử dụng một trong số các lệnh gọi javascript không hỗ trợ). Nhưng, thậm chí sau đó, tôi cảm thấy như bạn nên chọn để gọi db từ khách hàng hoặc gọi db từ máy chủ và, do đó, nó không có ý nghĩa nhiều để chia sẻ mã db hoặc.
  • Một khu vực chia sẻ chắc chắn có giá trị là có thể chia sẻ và chuyển cấu trúc dữ liệu clojure (kết hợp lồng nhau của danh sách, vectơ, tập hợp, v.v.) giữa máy khách và máy chủ. Không cần phải chuyển đổi thành json (hoặc xml) và ngược lại. Ví dụ, có thể vượt qua các biểu diễn kiểu nấc cục của mái vòm qua lại rất thuận tiện. Trong gwt, tôi đã sử dụng gilead để chia sẻ các mô hình giữa máy khách và máy chủ. Nhưng, trong clojure, bạn có thể đơn giản chuyển các cấu trúc dữ liệu xung quanh, vì vậy thực sự không cần phải chia sẻ các định nghĩa lớp như trong gwt.
  • Một lĩnh vực mà tôi cảm thấy cần thử nghiệm hơn là chia sẻ trạng thái giữa máy khách và máy chủ. Trong tâm trí của tôi có một vài chiến lược: lưu trữ trạng thái trên máy khách (các ứng dụng loại ajax đơn) hoặc trạng thái lưu trữ trên máy chủ (như các ứng dụng jsp cũ) hoặc kết hợp cả hai. Có lẽ mã chịu trách nhiệm cập nhật trạng thái (các nguyên tử, ref, đại lý hay bất cứ điều gì) có thể được chia sẻ và sau đó nhà nước có thể được chuyển qua lại theo yêu cầu và đáp ứng để giữ cho hai cấp trong đồng bộ? Cho đến nay, chỉ cần viết máy chủ bằng cách sử dụng các phương pháp hay nhất của REST và sau đó có trạng thái được lưu trữ trên máy khách dường như hoạt động khá tốt. Nhưng tôi có thể thấy làm thế nào có thể có lợi ích để chia sẻ trạng thái giữa khách hàng và máy chủ.
  • Tôi chưa cần chia sẻ Hằng số và/hoặc Thuộc tính, nhưng đây có thể là điều tốt để tái sử dụng. Nếu bạn đặt tất cả các hằng số toàn cầu của ứng dụng vào một tệp clj và sau đó đã viết một kịch bản để sao chép nó sang cljs bất cứ khi nào bạn biên dịch clojurescript, điều đó sẽ hoạt động tốt và có thể tiết kiệm một chút mã trùng lặp.

Hy vọng những suy nghĩ này hữu ích, tôi rất quan tâm đến những gì người khác đã tìm thấy cho đến nay!

+0

Điểm tuyệt vời! Tôi muốn thống nhất quy trình bằng cách có mã máy chủ của tôi tự động xây dựng tất cả mã Clojurescript của tôi bằng cách chuyển một tập hợp con các hàm của nó vào trình biên dịch. Tôi chưa đọc mã trình biên dịch, nhưng nó phải có khả năng cho nó biểu thức trực tiếp mà không cần sử dụng các tệp .cljs. – Hendekagon

+0

Về chia sẻ datastruture, thư viện 'fetch' có vẻ khá gọn gàng! https://github.com/ibdknox/fetch – leontalbot

2

Wrote một chút nhanh chóng mã để sao chép một tập hợp con của mã máy chủ clojure tôi trên mã clojurescript của tôi, đổi tên như .cljs trước tòa nhà:

(ns clj-cljs.build 
    (use 
    [clojure.java.io] 
) 
    (require 
    [cljs.closure :as cljsc] 
) 
) 

(defn list-files [path] 
(.listFiles (as-file path)) 
) 

(defn copy-file* [from to] 
;(println " coping " from " to " to) 
(make-parents to) 
(copy from to) 
)  

(defn rename [to-path common-path f] 
(str to-path common-path (.replaceAll (.getName f) ".clj" ".cljs")) 
) 

(defn clj-cljs* [files common-path to-path] 
    (doseq [i (filter #(.endsWith (.getName %) ".clj") files)] 
    (copy-file* i (file (rename to-path common-path i))) 
) 
    (doseq [i (filter #(.isDirectory %) files)] 
    (clj-cljs* (list-files i) (str common-path (.getName i) "/") to-path) 
) 
) 

(defn build [{:keys [common-path clj-path cljs-path js-path module-name]}] 
    (clj-cljs* (list-files (str clj-path common-path)) common-path cljs-path) 
    (cljsc/build 
    cljs-path 
    { 
    :output-dir js-path 
    :output-to (str js-path module-name ".js") 
    } 
) 
) 

(defn build-default [] 
    (build 
    { 
    :clj-path "/home/user/projects/example/code/src/main/clojure/" 
    :cljs-path "/home/user/projects/example/code/src/main/cljs/" 
    :js-path "/home/user/projects/example/code/public/js/cljs/" 
    :common-path "example/common/" ; the root of your common server-client code 
    :module-name "example" 
    } 
) 
) 
10

Các lein-cljsbuild plugin mới cho Leiningen đã xây dựng-in support để chia sẻ mã Clojure thuần túy.

+2

Hỗ trợ tích hợp [cljsbuild] (https://github.com/emezeske/lein-cljsbuild) được hỗ trợ (crossover) đã không được hỗ trợ cho [cljx] (https : //github.com/lynaghk/cljx), xem câu trả lời [this] (http://stackoverflow.com/a/10369314/1209442). –

15

Tôi đã viết plugin cljx Leiningen cụ thể để xử lý chia sẻ mã Clojure/ClojureScript cho thư viện trực quan hóa dữ liệu Clojure. 95% mã không phải host-interop trông giống nhau và cljx cho phép bạn tự động viết lại 5% cuối cùng bằng cách chỉ định quy tắc viết lại bằng cách sử dụng core.logic. Hầu hết thời gian, mặc dù, đó là biểu tượng thay thế đơn giản; Ví dụ: clojure.lang.IFn trong Clojure chỉ là IFn trong ClojureScript.

Bạn cũng có thể sử dụng siêu dữ liệu để chú thích các biểu mẫu được bao gồm hoặc loại trừ khi mã được tạo cho một nền tảng cụ thể.

+0

trông hữu ích cheerz – Hendekagon

+1

[cljx] (https://github.com/lynaghk/cljx) đã được thông qua như là công cụ chia sẻ mã được lựa chọn bởi [cljsbuild] (https://github.com/emezeske/lein-cljsbuild) –

0

Câu hỏi này đặt trước cljc, nhưng kể từ khi tôi tình cờ gặp nó, tôi nghĩ tôi sẽ đề cập đến Clojure reader conditionals.

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