From f686a27120e339fbdd91ef4489bff4669d7f9e67 Mon Sep 17 00:00:00 2001 From: Rafael Xavier de Souza Date: Fri, 14 Aug 2015 11:14:09 -0300 Subject: [PATCH] Examples: Include app example using webpack Fixes #464 Ref #398 Ref #441 Ref #467 --- README.md | 40 ++++++++-- examples/app-npm-webpack/.gitignore | 2 + examples/app-npm-webpack/README.md | 74 ++++++++++++++++++ examples/app-npm-webpack/app/index.js | 55 +++++++++++++ examples/app-npm-webpack/index-template.html | 82 ++++++++++++++++++++ examples/app-npm-webpack/messages/en.json | 17 ++++ examples/app-npm-webpack/messages/es.json | 17 ++++ examples/app-npm-webpack/messages/pt.json | 17 ++++ examples/app-npm-webpack/messages/zh.json | 17 ++++ examples/app-npm-webpack/package.json | 17 ++++ examples/app-npm-webpack/webpack-config.js | 54 +++++++++++++ 11 files changed, 385 insertions(+), 7 deletions(-) create mode 100644 examples/app-npm-webpack/.gitignore create mode 100644 examples/app-npm-webpack/README.md create mode 100644 examples/app-npm-webpack/app/index.js create mode 100644 examples/app-npm-webpack/index-template.html create mode 100644 examples/app-npm-webpack/messages/en.json create mode 100644 examples/app-npm-webpack/messages/es.json create mode 100644 examples/app-npm-webpack/messages/pt.json create mode 100644 examples/app-npm-webpack/messages/zh.json create mode 100644 examples/app-npm-webpack/package.json create mode 100644 examples/app-npm-webpack/webpack-config.js diff --git a/README.md b/README.md index dd14bc802..75d6428b4 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Node.js module. - [Usage](#usage) - [Performance](#performance) - [Compilation and the Runtime modules](#compilation-and-the-runtime-modules) + - [Examples](#examples) - [API](#api) - [Core](#core-module) - [Date module](#date-module) @@ -248,12 +249,8 @@ can cherry-pick the pieces you need, eg. load `dist/globalize.js` to get Globalize core, load `dist/globalize/date.js` to extend Globalize with Date functionalities, etc. -An example is worth a thousand words. Check out our Hello World demo (available -to you in different flavors): -- [Hello World (AMD + bower)](examples/amd-bower/). -- [Hello World (Node.js + npm)](examples/node-npm/). -- [Hello World (plain JavaScript)](examples/plain-javascript/). - +An example is worth a thousand words. Check out our [Examples](#examples) +section below. ### Performance @@ -290,7 +287,6 @@ created (see [Performance](#performance) above for more information). To illustrate, see our [Basic Globalize Compiler example][]. -[Basic Globalize Compiler example]: examples/globalize-compiler/ #### Globalize Compiler @@ -299,6 +295,36 @@ For information about the Globalize Compiler CLI or its JavaScript API, see the [Globalize Compiler documentation]: https://github.com/jquery-support/globalize-compiler#README +### Examples + +The fastest and easiest way to use Globalize is by integrating it into your +existing tools. + +- [Application example using webpack and npm](examples/app-npm-webpack/): easy to + get started, automated CLDR loading and precompilation for production, but + requires npm and webpack knowledge. + +If you're using a different tool than the one above, but you're comfortable +using JavaScript modules (such as ES6 modules, CommonJS, or AMD) and package +managers like npm or bower, you may want to check out the following examples. +Note you'll need to compile your code for production yourself. + +- [Basic example using AMD and bower](examples/amd-bower/): feeding Globalize on + CLDR is not completely transparent. +- [Basic example using Node.js and npm](examples/node-npm/): feeding Globalize + on CLDR is not completely transparent. +- [Basic Globalize Compiler example][]: shows how to use Globalize Compiler CLI. + +[Basic Globalize Compiler example]: examples/globalize-compiler/ + +If you're using none of the tools above, but instead you're using the plain and +old script tags only, the following example may interest you. Note Globalize +allows you to go low level like this. But, acknowledge that you'll need to +handle dependencies and CLDR loading manually yourself. + +- [Basic example using plain JavaScript](examples/plain-javascript/): requires + loading CLDR and handling dependencies manually. + ## API ### Core module diff --git a/examples/app-npm-webpack/.gitignore b/examples/app-npm-webpack/.gitignore new file mode 100644 index 000000000..3dfc3690d --- /dev/null +++ b/examples/app-npm-webpack/.gitignore @@ -0,0 +1,2 @@ +dist/ +.tmp-globalize-webpack/ diff --git a/examples/app-npm-webpack/README.md b/examples/app-npm-webpack/README.md new file mode 100644 index 000000000..ead9d4307 --- /dev/null +++ b/examples/app-npm-webpack/README.md @@ -0,0 +1,74 @@ +# Globalize App example using webpack + +This example demonstrates how to integrate Globalize with Webpack in your +Application. If you already have an existing Application using Webpack stack, +this example should as well provide you guidance on how to integrate Globalize. +It focuses on the [Globalize Webpack Plugin][], which automates data loading +(CLDR and app messages) during development and automates Globalize compilation +and the usage of Globalize runtime modules for production. It assumes knowledge +of Globalize, npm, and Webpack usage basics. + +## Requirements + +**1. Install app development dependencies** + +This example uses `npm` to download the app development dependencies (i.e., +Globalize, CLDR data, Cldrjs, Webpack, [Globalize Webpack Plugin][], and +others). + +``` +npm install +``` + +## Running the example + +### Development mode + +``` +npm start +``` + +1. Start a server by running `npm start`, which uses webpack's live reload HMR +(Hot Module Replacement). See `package.json` to understand the actual shell +command that is used. +1. Point your browser at `http://localhost:8080`. Note that your browser will +automatically reload on any changes made to the application code (`app/*.js` +files). Also note that for faster page reload, formatters are created +dynamically and automatically by the [Globalize Webpack Plugin][]. +1. Note you can specify the development locale of your choice by setting the +`developmentLocale` property of the Globalize Webpack Plugin on the Webpack +config file. +1. Note that CLDR data and your messages data are automatically loaded by the +[Globalize Webpack Plugin][]. +1. Understand the demo by reading the source code. We have comments there for +you. + +### Production mode + +``` +npm run build +``` + +1. Generate the compiled bundles by running `npm run build`, which will be +created at `./dist`. Note the production bundles are split into three chunks: +(a) vendor, which holds third-party libraries, which in this case means +Globalize Runtime modules, (b) i18n precompiled data, which means the minimum +yet sufficient set of precompiled i18n data that your application needs (one +file for each supported locale), and (c) app, which means your application code. +Also note that all the production code is already minified using UglifyJS. See +`package.json` to understand the actual shell command that is used. +1. Note that your formatters are already precompiled. This is +obvious, but worth emphasizing. It means your formatters are prebuilt, so no client +CPU clock is wasted to generate them and no CLDR or messages data needs to be +dynamically loaded. It means fast to load code (small code) and fast to run +code. +1. Point your browser at `./dist/index.html` to run the application using the +generated production files. Edit this file to display the application using a +different locale (source code has instructions). +1. Understand the demo by reading the source code. We have comments there for +you. + +For more information about the plugin, see the [Globalize Webpack Plugin][] +documentation. + +[Globalize Webpack Plugin]: https://github.com/rxaviers/globalize-webpack-plugin diff --git a/examples/app-npm-webpack/app/index.js b/examples/app-npm-webpack/app/index.js new file mode 100644 index 000000000..ad8ad29c7 --- /dev/null +++ b/examples/app-npm-webpack/app/index.js @@ -0,0 +1,55 @@ +var currencyFormatter, dateFormatter, numberFormatter, relativeTimeFormatter, startTime, + Globalize = require( "globalize" ); + +startTime = new Date(); + +currencyFormatter = Globalize.currencyFormatter( "USD" ); +dateFormatter = Globalize.dateFormatter({ datetime: "medium" }); +numberFormatter = Globalize.numberFormatter({ maximumFractionDigits: 2 }); +relativeTimeFormatter = Globalize.relativeTimeFormatter( "second" ); + +document.getElementById( "intro-1" ).innerHTML = Globalize.formatMessage( "intro-1" ); + +// Standalone table. +document.getElementById( "currency-label" ).innerHTML = Globalize.formatMessage( "currency-label" ); +document.getElementById( "currency" ).innerHTML = currencyFormatter( 69900 ); + +document.getElementById( "date-label" ).innerHTML = Globalize.formatMessage( "date-label" ); +document.getElementById( "date" ).innerHTML = dateFormatter( new Date() ); + +document.getElementById( "number-label" ).innerHTML = Globalize.formatMessage( "number-label" ); +document.getElementById( "number" ).innerHTML = numberFormatter( 12345.6789 ); + +document.getElementById( "relative-time-label" ).innerHTML = Globalize.formatMessage( "relative-time-label" ); +document.getElementById( "relative-time" ).innerHTML = relativeTimeFormatter( 0 ); + +// Messages. +document.getElementById( "message-1" ).innerHTML = Globalize.formatMessage( "message-1", { + currency: currencyFormatter( 69900 ), + date: dateFormatter( new Date() ), + number: numberFormatter( 12345.6789 ), + relativeTime: relativeTimeFormatter( 0 ) +}); + +document.getElementById( "message-2" ).innerHTML = Globalize.formatMessage( "message-2", { + count: 3 +}); + +// Display demo. +document.getElementById( "requirements" ).style.display = "none"; +document.getElementById( "demo" ).style.display = "block"; + +// Refresh elapsed time +setInterval(function() { + var elapsedTime = +( ( startTime - new Date() ) / 1000 ).toFixed( 0 ); + document.getElementById( "date" ).innerHTML = dateFormatter( new Date() ); + document.getElementById( "relative-time" ).innerHTML = relativeTimeFormatter( elapsedTime ); + document.getElementById( "message-1" ).innerHTML = Globalize.formatMessage( "message-1", { + currency: currencyFormatter( 69900 ), + date: dateFormatter( new Date() ), + number: numberFormatter( 12345.6789 ), + relativeTime: relativeTimeFormatter( elapsedTime ) + }); + +}, 1000); + diff --git a/examples/app-npm-webpack/index-template.html b/examples/app-npm-webpack/index-template.html new file mode 100644 index 000000000..7568c1844 --- /dev/null +++ b/examples/app-npm-webpack/index-template.html @@ -0,0 +1,82 @@ + + + + + + Globalize App example using Webpack + + + +

Globalize App example using Webpack

+ +
+

Requirements

+ +
+ + + +{% +var hasShownLocaleHelp; +for ( var chunk in o.htmlWebpackPlugin.files.chunks ) { + if ( /globalize-compiled-data-/.test( chunk ) && chunk !== "globalize-compiled-data-en" ) { + if ( !hasShownLocaleHelp ) { + hasShownLocaleHelp = true; +%} + +{% } %} + +{% } else { %} + +{% + } +} +%} + + + diff --git a/examples/app-npm-webpack/messages/en.json b/examples/app-npm-webpack/messages/en.json new file mode 100644 index 000000000..f830e3b96 --- /dev/null +++ b/examples/app-npm-webpack/messages/en.json @@ -0,0 +1,17 @@ +{ + "en": { + "intro-1": "Use Globalize to internationalize your application.", + "number-label": "Number", + "currency-label": "Currency", + "date-label": "Date", + "relative-time-label": "Relative Time", + "message-1": "An example of a message using mixed numbers \"{number}\", currencies \"{currency}\", dates \"{date}\", and relative time \"{relativeTime}\".", + "message-2": [ + "An example of a message with pluralization support:", + "{count, plural,", + " one {You have one remaining task}", + " other {You have # remaining tasks}", + "}." + ] + } +} diff --git a/examples/app-npm-webpack/messages/es.json b/examples/app-npm-webpack/messages/es.json new file mode 100644 index 000000000..654169b8c --- /dev/null +++ b/examples/app-npm-webpack/messages/es.json @@ -0,0 +1,17 @@ +{ + "es": { + "intro-1": "Use Globalize to internationalize your application.", + "number-label": "Standalone Number", + "currency-label": "Standalone Currency", + "date-label": "Standalone Date", + "relative-time-label": "Standalone Relative Time", + "message-1": "An example of a message using mixed numbers \"{number}\", currencies \"{currency}\", dates \"{date}\", and relative time \"{relativeTime}\".", + "message-2": [ + "An example of a message with pluralization support:", + "{count, plural,", + " one {You have one remaining task}", + " other {You have # remaining tasks}", + "}." + ] + } +} diff --git a/examples/app-npm-webpack/messages/pt.json b/examples/app-npm-webpack/messages/pt.json new file mode 100644 index 000000000..8fcba4705 --- /dev/null +++ b/examples/app-npm-webpack/messages/pt.json @@ -0,0 +1,17 @@ +{ + "pt": { + "intro-1": "Use o Globalize para internacionalizar sua aplicação.", + "number-label": "Número", + "currency-label": "Moeda", + "date-label": "Data", + "relative-time-label": "Tempo relativo", + "message-1": "Um exemplo de mensagem com mistura de números \"{number}\", moedas \"{currency}\", datas \"{date}\", e tempo relativo \"{relativeTime}\".", + "message-2": [ + "Um exemplo de message com suporte a pluralização:", + "{count, plural,", + " one {Você tem uma tarefa restante}", + " other {Você tem # tarefas restantes}", + "}." + ] + } +} diff --git a/examples/app-npm-webpack/messages/zh.json b/examples/app-npm-webpack/messages/zh.json new file mode 100644 index 000000000..5b7eb3085 --- /dev/null +++ b/examples/app-npm-webpack/messages/zh.json @@ -0,0 +1,17 @@ +{ + "zh": { + "intro-1": "Use Globalize to internationalize your application.", + "number-label": "Standalone Number", + "currency-label": "Standalone Currency", + "date-label": "Standalone Date", + "relative-time-label": "Standalone Relative Time", + "message-1": "An example of a message using mixed numbers \"{number}\", currencies \"{currency}\", dates \"{date}\", and relative time \"{relativeTime}\".", + "message-2": [ + "An example of a message with pluralization support:", + "{count, plural,", + " one {You have one remaining task}", + " other {You have # remaining tasks}", + "}." + ] + } +} diff --git a/examples/app-npm-webpack/package.json b/examples/app-npm-webpack/package.json new file mode 100644 index 000000000..df59271cf --- /dev/null +++ b/examples/app-npm-webpack/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "devDependencies": { + "cldr-data": ">=25", + "globalize": "1.1.0-alpha - 1.1.x", + "extract-text-webpack-plugin": "^0.8.2", + "globalize-webpack-plugin": "0.1.x", + "html-webpack-plugin": "^1.1.0", + "nopt": "^3.0.3", + "webpack": "^1.9.0", + "webpack-dev-server": "^1.9.0" + }, + "scripts": { + "start": "./node_modules/.bin/webpack-dev-server --config webpack-config.js --hot --progress --colors --inline", + "build": "./node_modules/.bin/webpack --production --config webpack-config.js" + } +} diff --git a/examples/app-npm-webpack/webpack-config.js b/examples/app-npm-webpack/webpack-config.js new file mode 100644 index 000000000..d013a4028 --- /dev/null +++ b/examples/app-npm-webpack/webpack-config.js @@ -0,0 +1,54 @@ +var webpack = require( "webpack" ); +var CommonsChunkPlugin = require( "webpack/lib/optimize/CommonsChunkPlugin" ); +var HtmlWebpackPlugin = require( "html-webpack-plugin" ); +var GlobalizePlugin = require( "globalize-webpack-plugin" ); +var nopt = require( "nopt" ); + +var options = nopt({ + production: Boolean +}); + +module.exports = { + entry: options.production ? { + main: "./app/index.js", + vendor: [ + "globalize", + "globalize/dist/globalize-runtime/number", + "globalize/dist/globalize-runtime/plural", + "globalize/dist/globalize-runtime/message", + "globalize/dist/globalize-runtime/currency", + "globalize/dist/globalize-runtime/date", + "globalize/dist/globalize-runtime/relative-time" + ] + } : "./app/index.js", + debug: !options.production, + output: { + path: options.production ? "./dist" : "./tmp", + publicPath: options.production ? "" : "http://localhost:8080/", + filename: options.production ? "app.[hash].js" : "app.js", + }, + resolve: { + extensions: [ "", ".js" ], + }, + plugins: [ + new HtmlWebpackPlugin({ + production: options.production, + template: "./index-template.html", + }), + new GlobalizePlugin({ + production: options.production, + developmentLocale: "en", + supportedLocales: [ "en", "es", "pt", "zh" ], + messages: "messages/[locale].json", + output: "i18n/[locale].[hash].js" + }) + ].concat( options.production ? [ + new webpack.optimize.DedupePlugin(), + new CommonsChunkPlugin( "vendor", "vendor.[hash].js" ), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false, + }, + }) + ] : [] ) +};