Javascriptモジュール

Odoo は 3 種類の javascript ファイルをサポートしています。

:ref:`assets management page <reference/assets>`で説明されているように、すべてのjavascriptファイルはまとめられ、ブラウザに提供されます。 ネイティブの javascript ファイルは、Odoo サーバーによって処理され、Odoo カスタムモジュールに変換されることに注意してください。

それぞれの種類の javascript ファイルの背後にある目的を簡単に説明しましょう。 プレーンな javascript ファイルは、外部ライブラリといくつかの小さな特定の低レベルの目的のためにのみ予約する必要があります。 すべての新しいjavascriptファイルは、ネイティブのjavascriptモジュールシステムで作成する必要があります。 カスタムモジュールシステムは、古いファイルではなく変換されていない場合にのみ役立ちます。

プレーンJavascriptファイル

プレーンな javascript ファイルには任意のコンテンツを含めることができます。このようなファイルを書くときは iife immediate function execution スタイルを使用することをお勧めします。

(function () {
  // some code here
  let a = 1;
  console.log(a);
})();

そのようなファイルの利点は、ローカル変数をグローバルスコープに漏らさないことです。

明らかに、プレーンな javascript ファイルは、モジュールシステムの利点を提供していません ですから、バンドル内の順序に注意する必要があります (ブラウザはその順序でそれらを正確に実行するため)。

注釈

Odoo では、すべての外部ライブラリがプレーンな javascript ファイルとして読み込まれます。

ネイティブJavascriptモジュール

Odoo javascript コードはネイティブの javascript モジュールシステムを使用します。 これにより、IDEとの統合が向上し、開発者エクスペリエンスが向上するという利点がもたらされます。

:file:`web/static/src/file_a.js`にある以下のモジュールを考えてみましょう。

import { someFunction } from "./file_b";

export function otherFunction(val) {
    return someFunction(val + 3);
}

デフォルトでは、/static/src`と/static/tests`の下のOdoo transpiles filesを :ref:`Odoo modules <frontend/modules/odoo_module>`にします。 このファイルは以下のようなOdooモジュールに転送されます:

odoo.define('@web/file_a', ['@web/file_b'], function (require) {
'use strict';
let __exports = {};

const { someFunction } = require("@web/file_b");

__exports.otherFunction = function otherFunction(val) {
   return someFunction(val + 3);
};

return __exports;
)};

ですから、変換は基本的に先頭に odoo.define を追加し、インポート/エクスポート文を更新します。 これはオプトアウトシステムで、トランスパイラーにファイルを無視するように指示することができます。

/** @odoo-module ignore **/
(function () {
  const sum = (a, b) => a + b;
  console.log(sum(1, 2));
)();

最初の行のコメントに注意してください: このファイルは無視されるべきであることを記述しています。

他のフォルダでは、ファイルはデフォルトでトランスパイルされません、それはオプトインです。 Odoo は JS ファイルの最初の行を見て、@odoo-module とタグなしでコメントが含まれているかどうかを確認します。 その場合、自動的に Odoo モジュールに変換されます。

/** @odoo-module **/
export function sum(a, b) {
  return a + b;
}

もう一つの重要な点は、トランスパイルされたモジュールに正式名称が*@web/file_a*であることです。 これはモジュールの実際の名前です。すべての相対インポートも変換されます。 Odoo addon some_addon/static/src/path/to/file.js 内にあるすべてのファイルには、以下のようなアドオン名が付与されます: @some_addon/path/to/file

相対インポートは動作しますが、モジュールが同じ Odoo アドオンの場合にのみ動作します。そのため、次のファイル構造があるとします。

addons/
    web/
        static/
            src/
                file_a.js
                file_b.js
    stock/
        static/
            src/
                file_c.js

ファイル file_bfile_a を以下のようにインポートできます。

import {something} from `./file_a`;

file_c はフルネームを使用する必要があります。

import {something} from `@web/file_a`;

エイリアスモジュール

Odoo modules は別のモジュール命名パターンに従っているためです。 新しいシステムへのスムーズな移行を可能にするシステムが存在する。 現在、ファイルがモジュールに変換されている場合(そのため、新しい命名規則に従ってください)。 プロジェクトで ES6 のような構文に変換されていない他のファイルは、モジュールを必要とすることはできません。 エイリアスは、小さなプロキシ機能を作成することで、古い名前と新しい名前をマップするためにここにあります。 このモジュールは、新しい and 古い名前で呼び出すことができます。

このようなエイリアスを追加するには、ファイルの上にあるコメントタグは次のようになります。

/** @odoo-module alias=web.someName**/
import { someFunction } from './file_b';

export default function otherFunction(val) {
    return someFunction(val + 3);
}

次に、翻訳されたモジュールは要求された名前のエイリアスも作成します:

odoo.define(`web.someName`, ['@web/file_a'], function(require) {
    return require('@web/file_a')[Symbol.for("default")];
});

エイリアスのデフォルトの動作は、エイリアスのモジュールの default 値を再エクスポートすることです。 これは、一般的に "classic" モジュールは、デフォルトのエクスポートのセマンティクスとほぼ一致する単一の値を直接使用するようにエクスポートするためです。 しかし、より直接に委任し、エイリアスされたモジュールの正確な挙動に従うこともできます。

/** @odoo-module alias=web.someName default=0**/
import { someFunction } from './file_b';

export function otherFunction(val) {
    return someFunction(val + 3);
}

この場合、元のモジュールでエクスポートされた値を使用してエイリアスを定義します。

odoo.define(`web.someName`, ["@web/file_a"], function(require) {
    return require('@web/file_a');
});

注釈

このメソッドを使用して1つのエイリアスのみ定義できます。 あなたが持っている別のものが必要な場合、例えば、 同じモジュールを呼び出すには3つの名前が必要です手動でプロキシを追加する必要があります これは良い方法ではなく、他の選択肢がない限り避けるべきです。

制約

パフォーマンス上の理由から、Odoo はネイティブモジュールを変換するために完全な javascript パーサを使用しません。 したがって、以下を含むが、これらに限定されない多くの制限があります。

  • import または export キーワードの前にスペースではない文字は使用できません。

  • 複数行のコメントまたは文字列は、`import`または`export`で始まる行を持つことはできません。

    // supported
    import X from "xxx";
    export X;
      export default X;
        import X from "xxx";
    
    /*
     * import X ...
     */
    
    /*
     * export X
     */
    
    
    // not supported
    
    var a= 1;import X from "xxx";
    /*
      import X ...
    */
    
  • オブジェクトをエクスポートするとき、コメントを含めることはできません。

    // supported
    export {
      a as b,
      c,
      d,
    }
    
    export {
      a
    } from "./file_a"
    
    
    // not supported
    export {
      a as b, // this is a comment
      c,
      d,
    }
    
    export {
      a /* this is a comment */
    } from "./file_a"
    
  • Odoo では、モジュールがパス ( ./views/form_view のような) で記述されているか、または名前(web.FormView のような)で記述されているかを判断する方法が必要です。 それを行うにはヒューリスティックを使用する必要があります。名前に`/がある場合、それはパスと見なされます。 これは、Odoo `/ のモジュール名を本当にサポートしていないことを意味します。

「クラシック」モジュールは非推奨であり、現在削除する計画はありません。 問題に遭遇したり、ネイティブモジュールの制限によって制約されている場合は、引き続き使用することができます。 両方のスタイルは、同じOdooアドオン内に共存することができます。

Odoo Module System

Odoo は小さなモジュールシステムを定義しています (最初にロードする必要がある :file:`addons/web/static/src/js/boot.js`ファイル内にあります)。 AMDに触発されたOdooモジュールシステムは、グローバルodoオブジェクトの関数`define`を定義することによって動作します。 その関数を呼び出すことで、各 javascript モジュールを定義します。 Odooフレームワークでは、モジュールはできるだけ早く実行されるコードです。 名前と依存関係がある可能性があります。 依存関係がロードされると、モジュールもロードされます。 モジュールの値は、モジュールを定義する関数の戻り値です。

例として、以下のようになります。

// in file a.js
odoo.define('module.A', [], function (require) {
    "use strict";

    var A = ...;

    return A;
});

// in file b.js
odoo.define('module.B', ['module.A'], function (require) {
    "use strict";

    var A = require('module.A');

    var B = ...; // something that involves A

    return B;
});

いくつかの依存関係が存在しない/準備ができていない場合、モジュールは単にロードされません。 数秒後にコンソールに警告が表示されます。

循環依存関係はサポートされていないことに注意してください。理にかなっていますが、注意する必要があることを意味します。

モジュールの定義

`odoo.define`メソッドには3つの引数が与えられます。

  • moduleName: javascriptモジュールの名前。一意の文字列である必要があります。 この規定は、アドオンの名前に、特定の記述を続けることになります。 例えば、 web.Widget は、 web アドオンで定義されたモジュールを説明しています。これは、 Widget クラス (最初の文字が大文字になっているため) をエクスポートします。

    名前が一意でない場合は、例外がスローされ、コンソールに表示されます。

  • dependencies: javascriptモジュールに対応する文字列のリストでなければなりません。 これはモジュールが実行される前にロードされるために必要な依存関係を説明します。

  • 最後に最後の引数はモジュールを定義する関数です 戻り値はモジュールの値で、それを必要とする他のモジュールに渡すことができます。

    odoo.define('module.Something', ['web.ajax'], function (require) {
        "use strict";
    
        var ajax = require('web.ajax');
    
        // some code here
        return something;
    });
    

エラーが発生した場合、コンソールにログ記録されます(デバッグモード)。

  • Missing dependencies: これらのモジュールはページに表示されません。 JavaScriptファイルがページに存在しないか、モジュール名が間違っている可能性があります。

  • 失敗したモジュール: javascriptエラーが検出されました

  • Rejected modules: The module returns a rejected Promise (and its dependent modules) is not loaded.

  • Rejected linked modules: rejected module に依存するモジュール

  • Non loaded modules: 不足または失敗したモジュールに依存するモジュール