DEV Community

loading...
Cover image for craftkit code pattern - Template for making package namespace

craftkit code pattern - Template for making package namespace

craftkitjs profile image CraftkitJS ・3 min read

In craftkit application, modules can be also used in HTML context. To avoid conflict of module name, you would like to define your package namespace.

This post illustrates key snippet about namespace, using implementation of your own package under the Craft.Widget namespace.

Steps

  • Define package namespace Craft.Widget.Example
  • Implement Craft.Widget.Example.View as a subclass of Craft.UI.View
  • Place the View on the screen
  • Overview, defining your own top level namespace

Files

Craft.Widget.Example/
├── package.json
├── index.js
├── index.min.js
├── main.js
├── View.js
├── webpack.config.js
└── index.html
Enter fullscreen mode Exit fullscreen mode

package.json

This is minimum version of package.json with craftkit.

{
  "name": "Craft.Widget.Example",
  "description": "",
  "version": "0.1.0",
  "dependencies": {
    "@craftkit/craft-uikit": "^3.1.4"
  },
  "devDependencies": {}
}
Enter fullscreen mode Exit fullscreen mode

index.js

The entry point of Node.js module.

'use strict';

const Example = require('./main.js');

module.exports = Example.default || Example;
Enter fullscreen mode Exit fullscreen mode

index.min.js

The entry point of HTML context. The namespace should be injected into the window object. This is done by Craft.usePackage function, and callbacked by it inject function. (When you define your own top level namespace, you should also define those functions to inject packages under the namespace. See the bottom of this post.)

'use strict';

const Example = require('./main.js');

window.Craft.usePackage(Example.default);

module.exports = Example.default || Example;
Enter fullscreen mode Exit fullscreen mode

main.js

Both Node.js and HTML context enter to this script at first.

To be able to make another packages join to this namespace, you should define inject function to the exporting object.

import { View } from './View.js';

const Packages = {
    View : View
};

Packages.inject = function(Craft){
    Craft.Widget = Craft.Widget || {};
    if( !Craft.Widget.Example ){
        Craft.Widget.Example = Packages;
    }
};

export default Packages;
Enter fullscreen mode Exit fullscreen mode

View.js

Main logic of this package.

This class will be accessible by Craft.Widget.Example.View.

import * as Craft from '@craftkit/craft-uikit';

export class View extends Craft.UI.View {
    template(componentId){
        return `
            <div class="root">
                This is Example
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

webpack.config.js

Write out package for HTML context.

var path = require('path');

module.exports = {
    mode: 'development',
    entry: './index.min.js',
    output: {
        path: path.resolve(__dirname,'./'),
        filename: 'craft-widget-example.min.js',
        library: 'Example',
        libraryTarget: 'window',
        globalObject: 'window'
    },
    externals: {
        '@craftkit/craft-uikit' : 'Craft',
    }
};
Enter fullscreen mode Exit fullscreen mode

index.html

HTML use case.

<html>
<head>
    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, viewport-fit=cover"/>

    <script src="https://unpkg.com/@craftkit/craft-uikit/dist/craft-uikit.min.js"></script>

    <script src="./craft-widget-example.min.js"></script>

    <script>
        window.onload = function(){
            Craft.Core.Bootstrap.boot({
                didBootApplication : function(options){
                    Craft.Core.Defaults.ALLOW_COMPONENT_SHORTCUT = true;
                    var rootViewController = new Craft.UI.DefaultRootViewController()
                    Craft.Core.Context.setRootViewController(rootViewController)

                    rootViewController.appendView(
                        new Craft.Widget.Example.View()
                    );
                }
            });
        };
    </script>
</head>
<body id="CraftRoot">
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Run

webpack --config webpack.config.js
Enter fullscreen mode Exit fullscreen mode

Then open ./index.html by browser.

Node.js context

In Node.js context, namespace is controlled under its rules.

To use full package name, call Craft.usePackage for your package.

import * as Craft from '@craftkit/craft-uikit';
import * as Example from './craft-widget-example';
Craft.usePackage(Example);

class MyPage extends Craft.UI.View {
    viewDidLoad(callback){
        this.appendView(new Craft.Widget.Example.View());
    }
}
Enter fullscreen mode Exit fullscreen mode

Define your own namespace

When you define your own top level namespace, like MyCompany.MyApp.Example, you may define something like this:

MyCompany/main.js

const MyCompany = {};

MyCompany.usePackage = function(packages){
    packages.inject(MyCompany);
};

export default MyCompany;
Enter fullscreen mode Exit fullscreen mode

MyCompany.MyApp.Example/main.js

import { View } from './View.js';

MyCompany.MyApp = {
    View : View
};

Packages.inject = function(MyCompany){
    MyCompany.MyApp = MyCompany.MyApp || {};
    if( !MyCompany.MyApp.Example ){
        MyCompany.MyApp.Example = Packages;
    }
};

export default MyCompany;
Enter fullscreen mode Exit fullscreen mode

index.min.js

'use strict';

const Example = require('./main.js');

window.MyCompany.usePackage(Example.default);

module.exports = Example.default || Example;
Enter fullscreen mode Exit fullscreen mode

index.html

rootViewController.appendView(new MyCompany.Widget.Example.View());
Enter fullscreen mode Exit fullscreen mode

YourApp.js

import * as MyCompany from '/mycompany';
import * as Example from './mycompany-myapp-example';
MyCompany.usePackage(Example);

class MyPage extends Craft.UI.View {
    viewDidLoad(callback){
        this.appendView(new MyCompany.MyApp.Example.View());
    }
}
Enter fullscreen mode Exit fullscreen mode

Discussion

pic
Editor guide