hybrid混合应用开发 (hybrid混合开发模式的技术栈)

1 集成要点

1.1 配置技巧

1.1.1 多入口配置

Multiple entry files are allowed. It is useful for a multi-page app.

// main1.js?1776922106.130

document.write('<h1>Hello World</h1>');

// main2.js?1776922106.130

document.write('<h2>Hello Webpack</h2>');

index.html

<html>

<body>

<script src="bundle1.js?1776922106.130 "></script>

<script src="bundle2.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

module.exports ={

entry:{

bundle1: './main1.js?1776922106.130 ',

bundle2: './main2.js?1776922106.130 '

},

output:{

filename: '[name].js?1776922106.130 '

}

};

1.1.2 CSS-loader

Demo04: CSS-loader(source)

Webpack allows you torequire CSS in JS file, then preprocessed CSS file with CSS-loader.

main.js?1776922106.130

require('./app.css?1776922106.130 ');

app.css?1776922106.130

body{

background-color: blue;

}

index.html

<html>

<head>

<script type="text/javascript" src="bundle.js?1776922106.130 "></script>

</head>

<body>

<h1>Hello World</h1>

</body>

</html>

webpack.config.js?1776922106.130

module.exports ={

entry: './main.js?1776922106.130 ',

output:{

filename: 'bundle.js?1776922106.130 '

},

module:{

loaders:[

{ test: /\.css$/, loader: 'style-loader!css-loader'},

]

}

};

Attention, you have to use two loaders to transform CSS file. First is CSS-loader to read CSS file, and another is Style-loader to insert Style tag into HTML page. Different loaders are linked by exclamation mark(!).

After launching the server, index.html will have internal stylesheet.

<head>

<script type="text/javascript" src="bundle.js?1776922106.130 "></script>

<style type="text/css">

body{

background-color: blue;

}

</style>

</head>

1.1.3 Imageloader

Demo05: Imageloader (source)

Webpack could also requireimages in JS files.

main.js?1776922106.130

var img1 = document.createElement("img");

img1.src = require("./small.png");

document.body.appendChild(img1);

var img2 = document.createElement("img");

img2.src = require("./big.png");

document.body.appendChild(img2);

index.html

<html>

<body>

<script type="text/javascript" src="bundle.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

module.exports ={

entry: './main.js?1776922106.130 ',

output:{

filename: 'bundle.js?1776922106.130 '

},

module:{

loaders:[

{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}

]

}

};

url-loader transforms image files.If the image size is smaller than 8192 bytes, it will be transformed into DataURL; otherwise, it will be transformed into normal URL. As you see, question mark(?) is used to pass parameters into loaders.

After launching the server, small.png and big.png will have the followingURLs.

<img src="data:image/png;base64,iVBOR...uQmCC">

<img src="4853ca667a2b8b8844eb2693ac1b2578.png">

1.1.4 代码混淆插件UglifyJs Plugin

Demo07: UglifyJsPlugin (source)

Webpack has a plugin system to expand its functions. For example, UglifyJs Plugin will minify output(bundle.js?1776922106.130 ) JS codes.

main.js?1776922106.130

var longVariableName = 'Hello';

longVariableName += ' World';

document.write('<h1>'+ longVariableName +'</h1>');

index.html

<html>

<body>

<script src="bundle.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

var webpack = require('webpack');

var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

module.exports ={

entry: './main.js?1776922106.130 ',

output:{

filename: 'bundle.js?1776922106.130 '

},

plugins:[

new uglifyJsPlugin({

compress:{

warnings: false

}

})

]

};

After launching the server, main.js?1776922106.130 will be minified into following.

var o="Hello"; o+=" World", document.write("<h1>" + o + "</h1>")

1.1.5 HTMLWebpack Plugin and Open Browser Webpack Plugin

Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin (source)

This demo shows you how toload 3rd-party plugins.

html-webpack-plugin could createindex.htmlforyou, and open-browser-webpack-plugin could open a new browser tab when Webpack loads.

main.js?1776922106.130

document.write('<h1>Hello World</h1>');

webpack.config.js?1776922106.130

var HtmlwebpackPlugin = require('html-webpack-plugin');

var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports ={

entry: './main.js?1776922106.130 ',

output:{

filename: 'bundle.js?1776922106.130 '

},

plugins:[

new HtmlwebpackPlugin({

title: 'Webpack-demos',

filename: 'index.html'

}),

new OpenBrowserPlugin({

url: 'http://localhost:8080'

})

]

};

Run webpack-dev-server.

$ webpack-dev-server

Now you don't need to write index.html by hand and don't have to open browser by yourself. Webpack did all these things for you.

1.1.6 环境标记

Demo09: Environmentflags (source)

You can enable some codes only in development environment with environment flags.

main.js?1776922106.130

document.write('<h1>Hello World</h1>');

if (__DEV__) {

document.write(new Date());

}

index.html

<html>

<body>

<script src="bundle.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({

__DEV__ : JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))

});

module.exports ={

entry: './main.js?1776922106.130 ',

output:{

filename: 'bundle.js?1776922106.130 '

},

plugins:[devFlagPlugin]

};

Now pass environment variable into webpack.

# Linux & Mac

$ env DEBUG=true webpack-dev-server

# Windows

$ setDEBUG=true

$ webpack-dev-server

1.1.7 代码分割Code splitting

Demo10: Codesplitting (source)

For big web apps it’s not efficient to put all code into a single file, Webpack allows you to split them into several chunks. Especially if some blocks of code are only required under some circumstances, these chunks could be loaded on demand.

At first, you use require.ensure to define a split point.(official document)

// main.js?1776922106.130

require.ensure(['./a'], function(require) {

var content = require('./a');

document.open();

document.write('<h1>' + content + '</h1>');

document.close();

});

require.ensure tells Webpack that ./a.js?1776922106.130 should be separated from bundle.js?1776922106.130 and built into a single chunk file.

// a.js?1776922106.130

module.exports = 'Hello World';

Now Webpack takes care of the dependencies, output files and runtime stuff. You don't have to put any redundancy into your index.html and webpack.config.js?1776922106.130 .

<html>

<body>

<script src="bundle.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

module.exports ={

entry : './main.js?1776922106.130 ',

output:{

filename : 'bundle.js?1776922106.130 '

}

};

Launch the server.

$ webpack-dev-server

On the surface, you won't feel any differences. However, Webpack actually builds main.js?1776922106.130 and a.js?1776922106.130 into different chunks(bundle.js?1776922106.130 and 1.bundle.js?1776922106.130 ), and loads 1.bundle.js?1776922106.130 from bundle.js?1776922106.130 when on demand.

1.1.8 bundle-loader切割代码Code splitting with bundle-loader

Demo11: Codesplitting with bundle-loader (source)

Another way of code splitting is using bundle-loader.

// main.js?1776922106.130

// Now a.js?1776922106.130 is requested, it will be bundled into another file

var load = require('bundle-loader!./a.js?1776922106.130 ');

// To wait until a.js?1776922106.130 is available (and get the exports)

// you need to async wait for it.

load(function(file) {

document.open();

document.write('<h1>' + file + '</h1>');

document.close();

});

require('bundle-loader!./a.js?1776922106.130 ') tells Webpack to load a.js?1776922106.130 from another chunk.

Now Webpack will build main.js?1776922106.130 into bundle.js?1776922106.130 , and a.js?1776922106.130 into 1.bundle.js?1776922106.130 .

1.1.9 用CommonsChunkPlugin提取通用代码块Common chunk

Demo12: Commonchunk (source)

When multi scripts have common chunks, you can extract the common part into a separate file withCommonsChunkPlugin.

// main1.js?1776922106.130 x

var React = require('react');

var ReactDOM = require('react-dom');

ReactDOM.render(<h1>Hello World</h1>, document.getElementById('a'));

// main2.js?1776922106.130 x

var React = require('react');

var ReactDOM = require('react-dom');

ReactDOM.render(<h2>Hello Webpack</h2>, document.getElementById('b'));

index.html

<html>

<body>

<div id="a"></div>

<div id="b"></div>

<script src="init.js?1776922106.130 "></script>

<script src="bundle1.js?1776922106.130 "></script>

<script src="bundle2.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");

module.exports ={

entry:{

bundle1: './main1.js?1776922106.130 x',

bundle2: './main2.js?1776922106.130 x'

},

output:{

filename: '[name].js?1776922106.130 '

},

module:{

loaders:[

{

test: /\.js[x]?$/,

exclude: /node_modules/,

loader: 'babel-loader',

query:{

presets: ['es2015', 'react']

}

},

]

},

plugins:[

new CommonsChunkPlugin('init.js?1776922106.130 ')

]

}

1.1.10 第三方库代码块Vendorchunk

Demo13: Vendorchunk (source)

You can also extract the vendor libraries from a script into a separate file with CommonsChunkPlugin.

main.js?1776922106.130

var $ = require('jquery');

$('h1').text('Hello World');

index.html

<html>

<body>

<h1></h1>

<script src="vendor.js?1776922106.130 "></script>

<script src="bundle.js?1776922106.130 "></script>

</body>

</html>

webpack.config.js?1776922106.130

var webpack = require('webpack');

module.exports ={

entry:{

app: './main.js?1776922106.130 ',

vendor: ['jquery'],

},

output:{

filename: 'bundle.js?1776922106.130 '

},

plugins:[

new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js?1776922106.130 ')

]

};

If you want a module available as variable in every module, such as making $ and jQuery available in every module without writing require("jquery"). You should use ProvidePlugin(Official doc).

// main.js?1776922106.130

$('h1').text('Hello World');

// webpack.config.js?1776922106.130

var webpack = require('webpack');

module.exports ={

entry:{

app: './main.js?1776922106.130 '

},

output:{

filename: 'bundle.js?1776922106.130 '

},

plugins:[

new webpack.ProvidePlugin({

$: "jquery",

jQuery: "jquery",

"window.jQuery": "jquery"

})

]

};

1.1.11 暴露全局变量

Demo14: Exposingglobal variables (source)

If you want to use some global variables, and don't want to include them in the Webpack bundle, you can enable externals field in webpack.config.js?1776922106.130 (official document).

For example, we have a data.js?1776922106.130 .

var data = 'Hello World';

We can expose data as a global variable.

// webpack.config.js?1776922106.130

module.exports ={

entry: './main.js?1776922106.130 x',

output:{

filename: 'bundle.js?1776922106.130 '

},

module:{

loaders:[

{

test: /\.js[x]?$/,

exclude: /node_modules/,

loader: 'babel-loader',

query:{

presets: ['es2015', 'react']

}

},

]

},

externals:{

//require('data') is external and available

// on the global var data

'data': 'data'

}

};

Now, you require data as a module variable in your script. but it actually is a global variable.

// main.js?1776922106.130 x

var data = require('data');

var React = require('react');

var ReactDOM = require('react-dom');

ReactDOM.render(<h1>{data}</h1>,

document.body

);

1.1.12 热更新HMR

Demo15: Hot ModuleReplacement (source)

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running without a page reload.

You have two ways to enable Hot Module Replacement with the webpack-dev-server.

(1) Specify --hot and --inline on the command line

$ webpack-dev-server --hot --inline

Meaning of the options:

• --hot: adds the HotModuleReplacementPlugin and switch theserver to hot mode.

• --inline: embed the webpack-dev-server runtime into the bundle.

• --hot --inline: also adds the webpack/hot/dev-serverentry.

(2) Modify webpack.config.js?1776922106.130 .

• add new webpack.HotModuleReplacementPlugin() to the plugins field

• add webpack/hot/dev-server and webpack-dev-server/client?http://localhost:8080 to the entry field

webpack.config.js?1776922106.130 looks like the following.

var webpack = require('webpack');

var path = require('path');

module.exports ={

entry:[

'webpack/hot/dev-server',

'webpack-dev-server/client?http://localhost:8080',

'./index.js?1776922106.130 '

],

output:{

filename: 'bundle.js?1776922106.130 ',

publicPath: '/static/'

},

plugins:[

new webpack.HotModuleReplacementPlugin()

],

module:{

loaders:[{

test: /\.jsx?$/,

exclude: /node_modules/,

loader: 'babel-loader',

query:{

presets: ['es2015', 'react']

},

include: path.join(__dirname, '.')

}]

}

};

Now launch the dev server.

$ webpack-dev-server

Visiting http://localhost:8080, you should see 'Hello World' in your browser.

Don't close the server. Open a new terminal to edit App.js?1776922106.130 , and modify 'Hello World' into 'Hello Webpack'. Save it, and see what happened in the browser.

App.js?1776922106.130

import React, { Component } from 'react';

export default class App extends Component{

render() {

return(<h1>Hello World</h1>);

}

}

index.js?1776922106.130

import React from 'react';

import ReactDOM from 'react-dom';

import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

index.html

<html>

<body>

<div id='root'></div>

<script src="/static/bundle.js?1776922106.130 "></script>

</body>

</html>

2 参考链接

webpack入门级教程

http://www.tuicool.com/articles/bA3eym7

WebPack简明学习教程

http://www.jianshu.com/p/b95bbcfc590d

[新姿势]前端革命,革了再革:WebPack

https://segmentfault.com/a/1190000002507327

WebPack:更优秀的模块依赖管理工具,及require.js?1776922106.130 的缺陷

http://www.kuqin.com/shuoit/20141221/344013.html

(Good)webpack解惑:多入口文件打包策略

http://www.cnblogs.com/lvdabao/p/5944420.html

webpack loader 列表

http://blog.csdn.net/keliyxyz/article/details/51649429

用Webpack打包你的一切

http://www.tuicool.com/articles/bIRBjmZ

使用 Webpack 模块化 Angular 应用程序

http://www.ibm.com/developerworks/cn/web/wa-modularize-angular-apps-with-webpack-trs/index.html

(Good)Angular中使用webpack基础篇

http://www.tuicool.com/articles/qQJfEju

(Good)Webpack + Angular的组件化实践

https://segmentfault.com/a/1190000003915443

AngularJS 进阶(一) 按需加载controller js (转帖)

https://my.oschina.net/sourcecoding/blog/304735

Code Splitting

https://webpack.js?1776922106.130 .org/guides/code-splitting/

(Good)webpack-demos

https://github.com/ruanyf/webpack-demos#demo12-common-chunk-source