---
slideOptions:
transition: slide
---
<!--
# 來來來,都打包,我們包好包滿:Webpack
-->
## 來來來,都打包,我們包好包滿:Webpack
Eden 2017.09.01
---
## 議程
1. 前端技術發展與趨勢
2. Webpack介紹
3. Sample 1 - basic
4. Sample 2 - import the system-web
5. Sample 3 - common template
6. Q & A
---
## 前端技術發展與趨勢
- AJAX
<span>jQuery<!-- .element: class="fragment highlight-blue" --></span>、Prototype、Dojo、ExtJS
- Chrome JavaScript V8引擎
Node.js
- 移動端應用
---
- 語言
CoffeeScript、<span>TypeScript<!-- .element: class="fragment highlight-blue" --></span>與<span>ES 2015<!-- .element: class="fragment highlight-blue" --></span>
- 樣式:框架、預處理器
<span>Twitter Bootstrap<!-- .element: class="fragment highlight-blue" --></span>、LESS、<span>SASS<!-- .element: class="fragment highlight-blue" --></span>、Stylus和<span>PostCSS<!-- .element: class="fragment highlight-blue" --></span>
- JavaScript模組管理
<span>AMD<!-- .element: class="fragment highlight-blue" --></span>、<span>CMD<!-- .element: class="fragment highlight-blue" --></span>、KMD、SeaJS、RequireJS
- 套件管理工具
components、bower、spm、<span>npm<!-- .element: class="fragment highlight-blue" --></span>、<span>yarn<!-- .element: class="fragment highlight-blue" --></span>
---
- 規範和標準:Web Components
- JS調試
- 自動化測試
PhantomJS、<span>WebDriver<!-- .element: class="fragment highlight-blue" --></span>
- 構建工具
grunt、browserify、<span>gulp<!-- .element: class="fragment highlight-blue" --></span>、<span>webpack<!-- .element: class="fragment highlight-blue" --></span>、jspm
---
## Webpack
---
<!-- .slide: data-background="http://i.imgur.com/hMOSBxi.png" data-background-color="#fff" -->
---
Webpack作用是對項目中的靜態資源進行統一管理,為項目的發佈提供最優的打包和部署方案。
主要特性:
- Support at CommonJS and AMD to bundle
- loaders
- plugins
- web-dev-server
---
## Sample 1 - Basic
---
### package.json
```json
{
...,
"scripts": {
"start": "./node_modules/.bin/webpack",
"start-run": "./node_modules/.bin/webpack && node dist/bundle.js",
"build": "./node_modules/.bin/webpack -p"
},
"dependencies": {
"babel-core": "^6.22.1",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.22.0",
"webpack": "^3.4.1"
}
}
```
---
### webpack.config.js
```javascript
const path = require('path');
module.exports = {
context: path.resolve(__dirname, './src'),
entry: './js/app.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
// 舊寫法(不推):
// loader: 'babel-loader?presets[]=es2015'
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
},
},
include: path.resolve(__dirname, 'src/js'),
exclude: /node_modules/,
},
]
},
};
```
---
## Sample 2 - Import the System-web
---
### package.json
```json
{
...,
"scripts": {
"watch": "cross-env NODE_ENV=production ./node_modules/.bin/webpack --progress -p --watch",
"build": "cross-env NODE_ENV=production ./node_modules/.bin/webpack --progress -p"
},
"author": "eden90267",
"license": "ISC",
"devDependencies": {},
"dependencies": {
"babel-core": "^6.22.1",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-stage-0": "^6.24.1",
"cross-env": "^5.0.0",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.1",
"html-loader": "^0.5.0",
"html-webpack-plugin": "^2.28.0",
"node-sass": "^4.4.0",
"raw-loader": "^0.5.1",
"postcss": "^6.0.6",
"postcss-loader": "^2.0.6",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.1",
"url-loader": "^0.5.7",
"webpack": "^3.4.1"
}
}
```
---
### webpack.config.js
```javascript
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ENV = process.env.NODE_ENV || 'development';
const DEV_MODE = ENV === 'development';
console.log(`DEV_MODE:${DEV_MODE}`);
const toFilename = (name, ext = 'js') => {
const units = [name, '.', ext];
if (!DEV_MODE) {
const hashStr = (ext === 'css' ? '-[contenthash]' : '-[chunkhash]');
units.splice(1, 0, hashStr);
}
return units.join('');
};
module.exports = {
context: path.join(__dirname),
entry: {
app: ['./src/js/app.js'],
},
output: {
filename: toFilename('app'),
path: path.resolve(__dirname, 'system-web/src/main/webapp/resources/js')
},
devtool: "source-map",
resolve: {
modules: [
path.resolve('src/sass'),
path.resolve('system-web/src/main/webapp/resources/js'),
path.resolve('node_modules'),
],
extensions: [".js"]
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',// presets 搬到 .babelrc
},
exclude: /node_modules/,
},
{
test: /\.sass$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {sourceMap: true},
},
{
loader: 'postcss-loader',
options: {sourceMap: true},
},
{
loader: 'sass-loader',
options: {sourceMap: true},
},
],
}),
include: [
path.resolve(__dirname, "src/sass")
],
exclude: /node_modules/,
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(ENV),
}),
new ExtractTextPlugin(toFilename("../css/app", "css")),
new HtmlWebpackPlugin({
filename: '../../template/templateBS.xhtml',
template: 'src/template/__templateBS__.xhtml',
inject: false,
})
]
};
```
---
## Sample 3 - Common Template
---
### package.json
```json
{
...,
"scripts": {
"start": "./node_modules/.bin/webpack-dev-server --progress --hot --devtool eval",
"build": "cross-env NODE_ENV=production ./node_modules/.bin/webpack --progress -p"
},
"devDependencies": {
"webpack-dev-server": "^2.5.1"
},
"dependencies": {
"babel-core": "^6.22.1",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.22.0",
"babel-preset-stage-0": "^6.24.1",
"cross-env": "^5.0.0",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.1",
"html-loader": "^0.5.0",
"html-webpack-plugin": "^2.28.0",
"img-loader": "^2.0.0",
"node-sass": "^4.4.0",
"pug": "^2.0.0-rc.2",
"pug-html-loader": "^1.1.5",
"pug-loader": "^2.3.0",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.5",
"style-loader": "^0.18.1",
"url-loader": "^0.5.7",
"webpack": "^3.4.1"
}
}
```
---
### webpack.config.js
```javascript
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ENV = process.env.NODE_ENV || 'development';
const DEV_MODE = ENV === 'development';
console.log(`DEV_MODE:${DEV_MODE}`);
const toFilename = (name, ext = 'js') => {
const units = [name, '.', ext];
if (!DEV_MODE) {
const hashStr = (ext === 'css' ? '-[contenthash]' : '-[chunkhash]');
units.splice(1, 0, hashStr);
}
return units.join('');
};
module.exports = {
context: path.join(__dirname, '/src'),
entry: {
app: ['./js/app.js'],
},
output: {
filename: toFilename('app'),
path: path.resolve(__dirname, 'dist'),
publicPath: DEV_MODE ? 'http://localhost:8080/' : '',
},
resolve: {
modules: [
path.resolve('src/html'),
path.resolve('src/img'),
path.resolve('src/css'),
path.resolve('src/js'),
path.resolve('node_modules'),
],
extensions: [".js"]
},
module: {
rules: [{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',// presets 搬到 .babelrc
},
exclude: /node_modules/,
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: { sourceMap: true },
},
{
loader: 'sass-loader',
options: { sourceMap: true },
},
],
}),
include: path.resolve(__dirname, "src/css"),
exclude: /node_modules/,
},
{
test: /\.pug$/,
use:[
{
loader: 'html-loader',
},
{
loader: 'pug-html-loader',
options: {
pretty: DEV_MODE,
},
}
],
include: path.resolve(__dirname, "src/html"),
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg|ico)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 2048,
name: "asset/[path][name].[ext]?[hash:10]",
},
},
],
include: path.resolve('src/img'),
exclude: /node_modules/,
},
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(ENV),
}),
new HtmlWebpackPlugin({
template: './html/index.pug',
}),
new ExtractTextPlugin( toFilename("css/app","css")),
],
devServer: {
contentBase: "dist",
port: 8080,
stats: {
chunks: false,
},
},
};
```
---
## Q & A
---