frontend-app v2.2.0
frontend-app
Start using latest ES syntax and features, Livereload and Hot Module Replacement.
This includes babel-polyfill and whatwg-fetch polyfill and transpiles code using env and stage-0 Babel presets, so you may use many new features of the language out-of-the-box.
JSX and AngularJS dependency injection annotations (babel-plugin-ng-annotate, ng-annotate) are also supported.
Contents
- Getting Started
- Commands
- Scripts
- Options
- React Intl helper Components
- List of Preconfigured Loaders
- Livereload
- Dev Server
- Single Entry
- Multiple Entries
- Examples
- Webpack Configuration
- Cookbook
Getting Started
Make sure you have at least Node.js 6.13.1 and npm 5.2 installed:
node -v
npm -v
Create package.json and install frontend-app:
mkdir my-app
cd my-app
npm init -y
npm install --save-dev frontend-app
Install one of the examples, have your app entry point(s) in src directory and webpack.config.js in place. Then build using:
npm run buildCommands
init
Initialize example project.
npx frontend-app init <example-name>Scripts
build
Files are transpiled, bundled and minified to the dist directory and are ready to be served. Source maps are also generated.
You may pass additional arguments to Webpack using --. For example, don't show progress information:
npm run build -- --progress falsedev
Bundle files to disk in watch mode (see Livereload).
dev-server
Bundle files in watch mode (see Dev Server).
Options
You may use package.json config field to set options. Example:
{
"name": "my-app",
"config": {
"frontendApp": {
"type": "react",
"port": "8080",
"devServer": {
"port": "8081"
}
}
}
}type
react: Adds JSX support.angular: Adds ng-annotate support.all: Support JSX and ng-annotate.ng-strict-diis not supported in livereload mode.slim(default): Just ES2015. No React or Angular specific transformations.portlet: Setsoutput.publicPathin Spring MVC Liferay plugin project built with Maven.publicPathis determined byartifactIdinpom.xml.
Multiple values are also supported. package.json config.frontendApp property example:
{
"type": ["angular", "portlet"]
}intl
Set "intl": "true" to use default list of available locales.
intl.locales
Available locales for Moment.js, React Intl and Intl. Default: ["fi", "sv", "en"] (When "intl": "true").
polyfills
Included polyfills. Default: ["babel-polyfill", "whatwg-fetch"]. Set "false" to not include any polyfills.
React Intl helper Components
Moved to @visma/react-intl-helpers.
List of Preconfigured Loaders
| Extension | Loader |
|---|---|
| JS | |
.js | (ng-annotate-loader,) babel-loader |
| HTML | |
.html | raw-loader |
.hbs | handlebars-template-loader |
| Styles | |
.css | css-loader |
.scss | sass-loader |
.less | less-loader |
| Fonts & Media | |
.woff, .woff2 | url-loader |
.ttf | url-loader |
.eot | file-loader |
.svg | url-loader |
.png | url-loader |
.gif | file-loader |
.jpg | file-loader |
| Other | |
.txt | raw-loader |
.properties | @visma/react-intl-helpers/cjs/loader |
Livereload
Start build process, watch changes and refresh browser automatically on changes.
npm run devIf you wish to serve files from different directory while developing (i.e. server content base is elsewhere):
npm run dev -- --output-path /some/other/content/base/distDev Server
Use this for Hot Module Replacement with React or as an alternative to Livereload.
npm run dev-serverSingle Entry (src/index.js)
my-app/
dist/ // generated
bundle.aa4915533a5b5f53c072.css
bundle.aa4915533a5b5f53c072.css.map
bundle.aa4915533a5b5f53c072.js
bundle.aa4915533a5b5f53c072.js.map
src/
index.js // entry point
other.js
package.json<link href="/dist/bundle.aa4915533a5b5f53c072.css" rel="stylesheet">
<script src="/dist/bundle.aa4915533a5b5f53c072.js"></script>Multiple Entries (src/entries)
my-app/
dist/ // generated
commons.ee0ce0879c8b5aaefae4.css
commons.ee0ce0879c8b5aaefae4.css.map
commons.ee0ce0879c8b5aaefae4.js
commons.ee0ce0879c8b5aaefae4.js.map
entries/pageA/bundle.8036db3af1be1831e295.css
entries/pageA/bundle.8036db3af1be1831e295.css.map
entries/pageA/bundle.8036db3af1be1831e295.js
entries/pageA/bundle.8036db3af1be1831e295.js.map
entries/pageB/bundle.19596c286128bce14cf9.css
entries/pageB/bundle.19596c286128bce14cf9.css.map
entries/pageB/bundle.19596c286128bce14cf9.js
entries/pageB/bundle.19596c286128bce14cf9.js.map
src/
entries/ // entry points e.g. for each page
pageA.js
pageB.js
other.js
package.jsonYou must load commons bundle before the entry point. pageA.html:
<link href="/dist/commons.ee0ce0879c8b5aaefae4.css" rel="stylesheet">
<link href="/dist/entries/pageA/bundle.8036db3af1be1831e295.css" rel="stylesheet">
<script src="/dist/commons.ee0ce0879c8b5aaefae4.js"></script>
<script src="/dist/entries/pageA/bundle.8036db3af1be1831e295.js"></script>Examples
React
Install example project with React Router, React-Bootstrap, Bootstrap 3 custom build, React Intl and mock API:
npx frontend-app init react
Start Webpack Dev Server:
npm run dev-server
Go to http://localhost:8080/.
React (multiple entries)
Install React example project for multi-portlet use, with Bootstrap 3 custom build, React Intl and mock API:
npx frontend-app init react-multiple-entries
Start Webpack Dev Server:
npm run dev-server
Go to http://localhost:8080/.
Angular
Install example project with AngularUI Router and Bootstrap:
npx frontend-app init angular
Start Webpack Dev Server:
npm run dev-server
Go to http://localhost:8080/.
Webpack Configuration
Provide the built-in Webpack configuration. webpack.config.js:
module.exports = require("frontend-app/cjs/webpack/config").default;Optionally merge own configuration. It will be merged into the built-in configuration using webpack-merge in smartStrategy mode:
module.exports = require("frontend-app/cjs/webpack/config").default.merge({
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
include: join(process.cwd(), "node_modules/my-lib")
}
]
},
output: {
publicPath: "/dist/"
}
});And/or customize the final configuration:
module.exports = require("frontend-app/cjs/webpack/config")
.default.merge({
output: {
publicPath: "/dist/"
}
})
.customize(config => {
// Edit entries.
config.entry[2] = join(config.entry[2], "client");
return config;
});Cookbook
History API Fallback with HTML Webpack Plugin
Suppose there is no backend or it's on another machine, and you just need to test some frontend code with Webpack Dev Server.
Install dependencies:
npm install --save-dev html-webpack-plugin
Edit webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = require("frontend-app/cjs/webpack/config").default.merge({
output: {
publicPath: "/dist/"
},
devServer: {
// Webpack Dev Server needs generated index.html in /dist directory for historyApiFallback to work.
historyApiFallback: { index: "/dist/" }
},
plugins: [
new HtmlWebpackPlugin({
title: "My App"
})
]
});CKEditor from /libs/ckeditor
Install dependencies:
npm install --save-dev html-webpack-plugin html-webpack-template
Edit webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = require("frontend-app/cjs/webpack/config").default.merge({
plugins: [
new HtmlWebpackPlugin({
inject: false,
template: require("html-webpack-template"),
scripts: ["/libs/ckeditor/ckeditor.js"],
window: {
CKEDITOR_BASEPATH: "/libs/ckeditor/"
}
})
]
});
Use CKEDITOR in your app:
// CKEDITOR is available.
window.CKEDITOR;CKEditor from node_modules
Install dependencies:
npm install --save-dev html-webpack-plugin html-webpack-template ckeditor
Edit webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = require("frontend-app/cjs/webpack/config").default.merge({
plugins: [
new HtmlWebpackPlugin({
inject: false,
template: require("html-webpack-template"),
window: {
CKEDITOR_BASEPATH: "/node_modules/ckeditor/"
}
})
]
});
Use CKEDITOR in your app:
import "ckeditor";
// CKEDITOR is available.
window.CKEDITOR;Different output.publicPath in production
process.env.NODE_ENV is set correctly. You may use NODE_ENV, and for example process.env.npm_lifecycle_event to customize your configuration. webpack.config.js:
const production = process.env.NODE_ENV === "production";
// process.env.npm_lifecycle_event => "build" | "dev" | "dev-server"
module.exports = require("frontend-app/cjs/webpack/config").default.merge({
output: {
publicPath: production ? "/somepath/dist/" : "/dist/"
}
});Maven
Install in webapp directory:
cd .../src/main/webapp
npm init
npm install --save-dev frontend-app
Add build step to pom.xml:
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>::install node and npm::</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>::npm ci::</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>ci</arguments>
</configuration>
</execution>
<execution>
<id>::npm run build::</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
<configuration>
<nodeVersion>v8.12.0</nodeVersion>
<npmVersion>6.4.1</npmVersion>
<workingDirectory>src/main/webapp</workingDirectory>
</configuration>
</plugin>
Add exclude rules to pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warSourceExcludes>src/,node/,node_modules/,package.json</warSourceExcludes>
<webResources>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
<excludes>
<exclude>src/**</exclude>
<exclude>node/**</exclude>
<exclude>node_modules/**</exclude>
<exclude>package.json</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>.gitignore
/dist/
/node_modules/7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago