Hello Word

Generate hello Bundle :

Command console to Generate new bundle : generate:bundle name path



$ nodefony generate:bundle hello src/bundles

# Or Interactive Mode

$ nodefony

Wed Mar 27 2019 15:12:41 INFO nodefony : WELCOME PROJECT : nodefony-starter 1.0.0
?  Nodefony CLI :  Generater
?  Nodefony CLI :  (Use arrow keys)
❯ Generate New Bundle
  Generate New Controller
  Generate New Service
  Generate New Entity
  Generate New Nodefony Project
  Generate Openssl Certificates
  Generate Haproxy Configuration
  Generate Nginx Configuration
  Generate letsEncrypt Webroot Configuration
  --------
  Quit
       __ _    ___   _ __     ___   _ __    __ _  | |_    ___
      / _` |  / _ \ | '_ \   / _ \ | '__|  / _` | | __|  / _ \
     | (_| | |  __/ | | | | |  __/ | |    | (_| | | |_  |  __/
      \__, |  \___| |_| |_|  \___| |_|     \__,_|  \__|  \___|
      |___/


   Wed Mar 27 2019 15:13:33 INFO COMMAND : generate:bundle
  ? Generate Nodefony Bundle :  nodefony

? Enter Bundle Name hello
? Enter Bundle Path /Users/cci/repository/nodefony-starter/src/bundles
? Do You Want To Build Matrice C++ addon ? No
 Wed Mar 27 2019 15:13:51 INFO nodefony : GENERATE bundle : hello-bundle LOCATION : /Users/cci/repository/nodefony-starter/src/bundles
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :hello-bundle
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :controller
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :defaultController.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :Resources
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :config
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :config.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :routing.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :security.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :services.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :webpack.config.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :webpack
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :webpack.dev.config.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :webpack.prod.config.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :public
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :hello.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :css
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :hello.css
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :images
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :assets
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :css
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :fonts
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :images
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :translations
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :views
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :index.html.twig
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :tests
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :helloTest.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :Command
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :helloCommand.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :helloTask.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :services
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :doc
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :readme.md
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :helloBundle.js
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :readme.md
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :src
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :Entity
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :package.json
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create Directory :build
 Wed Mar 27 2019 15:13:51 INFO BUILDER : Create File      :.gitignore
 Wed Mar 27 2019 15:13:51 INFO nodefony : Spawn : npm install

...

Example files system after Generate Bundle :

$ ls -l src/bundles/hello-bundle

drwxr-xr-x    4 cci  staff     128 27 mar 15:13 Command
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 Entity
drwxr-xr-x    6 cci  staff     192 27 mar 15:13 Resources
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 build
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 controller
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 doc
-rw-r--r--    1 cci  staff     642 27 mar 15:13 helloBundle.js
drwxr-xr-x  646 cci  staff   20672 27 mar 15:14 node_modules
-rw-r--r--    1 cci  staff  297699 27 mar 15:14 package-lock.json
-rw-r--r--    1 cci  staff    1274 27 mar 15:14 package.json
-rw-r--r--    1 cci  staff       1 27 mar 15:13 readme.md
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 services
drwxr-xr-x    2 cci  staff      64 27 mar 15:13 src
drwxr-xr-x    3 cci  staff      96 27 mar 15:13 tests

AUTO REGISTRATION :

The bundle generation engine auto registre generated bundle in framework :
During the generation of a bundle nodefony uses a temporary yml file ./config/generatedConfig.yml

./config/generatedConfig.yml


system:
  bundles:
    hello: src/bundles/hello-bundle

If the bundle is to be used in a durable way It is preferable to register the bundles in framework config file : ./config/config.js

./config/config.js
module.exports = {

  /**
   *  BUNDLES LOCAL REGISTRATION
   *
   *       bundles:{
   *         hello-bundle : "file:src/bundles/hello-bundle"
   *       }
   *
   */
  bundles: {
    "hello-bundle": "file:src/bundles/hello-bundle"
  }

}

Generated VIEW :

src/bundles/hello-bundle/Resources/views/index.html.twig
{% extends '/app/Resources/views/base.html.twig' %}

{% block title %}Welcome {{name}}! {% endblock %}

{% block stylesheets %}
  {{ parent() }}
  <!-- WEBPACK BUNDLE -->
  <link rel='stylesheet' href="{{CDN("stylesheet")}}/hello-bundle/assets/css/hello.css" />
{% endblock %}

{% block body %}
  {% block header %}
    {{ render( controller('app:app:header' )) }}
  {% endblock %}

  <div class='container' style='margin-top:100px'>
    <div class='row'>
      <div class='col text-center'>
        <img src="{{CDN("image")}}/app/images/app-logo.png">
        <a href='#'>
          <strong style='font-size:45px'>{{name}}</strong>
        </a>
        <p class='display-4 mt-5'>{{trans('welcome')}}</p>
        <p>{{binding}}</p>
        </div>
    </div>
  </div>

  {% block footer %}
    {{ render( controller('app:app:footer' )) }}
  {% endblock %}
{% endblock %}

{% block javascripts %}
  {{ parent() }}
  <!-- WEBPACK BUNDLE -->
  <script src="{{CDN("javascript")}}/hello-bundle/assets/js/hello.js"></script>
{% endblock %}

Generated Controller :

src/bundles/hello-bundle/controller/defaultController.js
/**
 *	@class defaultController
 *	@constructor
 *	@param {class} container
 *	@param {class} context
 *
 */
module.exports = class defaultController extends nodefony.controller {

  constructor (container, context){
    super(container, context);
  }

  /**
   *
   *	@method indexAction
   *
   */
  indexAction (){

    return this.render("hello-bundle::index.html.twig", {
      name: "hello-bundle"
    }).catch((e) =>{
        throw e ;
    });

  }
};

WATCHER FILES DURING DEVELOPMENT :

The bundle generation engine build bundle config with node.js watcher configuration
In developement mode is very usefull to auto-reload files as controllers , views , routing , translations
without having to reboot the server.

./src/bundles/hello-bundle/Resources/config/config.js
module.exports = {

  /**
   *    WATCHERS
   *
   *  watchers Listen to changes, deletion, renaming of files and directories
   *  of different components
   *
   *  For watch all components
   *      watch:                    true
   *  or
   *      watch:{
   *        controller:             true,
   *        config:                 true,        // only  routing.js
   *        views:                  true,
   *        translations:           true,
   *        webpack:                true
   *      }
   *
   */
  watch: true

};

WEBPACK MODULE BUNDLER :

The bundle generation engine build bundle config with a predefined webpack configurations
In this way webpack is very usefull to manage all assets of bundle
In developement mode watch is very usefull to auto-compile webpack module bundle
without having to reboot the server.

./src/bundles/hello-bundle/Resources/config/webpack.config.js
const path = require("path");
//const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpackMerge = require('webpack-merge');

// Default context 
//const context = path.resolve(__dirname, "..", "Resources", "public");
const public = path.resolve(__dirname, "..", "public", "assets");
const bundleName = path.basename(path.resolve(__dirname, "..", ".."));
const publicPath = bundleName + "/assets/";

let config = null;
let dev = true;
if (kernel.environment === "dev") {
  config = require("./webpack/webpack.dev.config.js");
} else {
  config = require("./webpack/webpack.prod.config.js");
  dev = false;
}

module.exports = webpackMerge(config, {
  //context: context,
  target: "web",
  entry: {
    hello  : [ "./Resources/public/js/hello.js" ]
  },
  output: {
    path: public,
    publicPath: publicPath,
    filename: "./js/[name].js",
    library: "[name]",
    libraryExport: "default"
  },
  externals: {},
  resolve: {},
  module: {
    rules: [{
        // BABEL TRANSCODE
        test: new RegExp("\.es6$|\.js$"),
        exclude: new RegExp("node_modules"),
        use: [{
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }]
      },
      /*
       *	JQUERY EXPOSE BROWSER CONTEXT
       *
       */
      {
        test: require.resolve("jquery"),
        loader: "expose-loader?$!expose-loader?jQuery"
      }, {
        test: /jquery\..*\.js/,
        loader: "imports-loader?$=jquery,jQuery=jquery,this=>window"
      }, {
        test: /\.(sa|sc|c)ss$/,
        use: [
          //'css-hot-loader',
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              sourceMap: true
            }
          }, {
            loader: 'resolve-url-loader',
            options: {}
          }, {
            loader: 'postcss-loader', // Run post css actions
            options: {
              plugins: () => [require('precss'), require('autoprefixer')]
            }
          }, {
            loader: "sass-loader",
            options: {
              sourceMap: true
            }
          }
        ]
      }, {
        test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/', // where the fonts will go
            publicPath: `/${bundleName}/assets/fonts/` // override the default path
          }
        }]
      }, {
        // IMAGES
        test: /\.(gif|png|jpe?g|svg)$/i,
        use: [{
          loader: "file-loader",
          options: {
            name: "[name].[ext]",
            publicPath: `/${bundleName}/assets/images/`,
            outputPath: "/images/"
          }
        }]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "./css/[name].css",
      allChunks: true
    })
  ],
  devServer: {
    inline: true,
    hot: false
  }
});

./src/bundles/hello-bundle/Resources/config/webpack/webpack.dev.config.js
const CleanWebpackPlugin = require('clean-webpack-plugin');
//const public = path.resolve(__dirname, "..", "..", "public");

module.exports = {
  mode: "development",
  devtool: "source-map",
  resolve: {},
  plugins: [
    new CleanWebpackPlugin({
      verbose: kernel.debug
    })
    //new webpack.NamedModulesPlugin(),
    //new webpack.HotModuleReplacementPlugin()
  ]
};

Start Nodefony to check new Bundle hello:

-d for debug mode
$ nodefony -d dev
 or
$ nodefony dev
Access to bundle route with URL : http://mydomain.com:5151/hello