--- 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 ---