【Hybrid开发高级系列】AngularJS集成Webpack专题

1 集成要点

1.1 配置技巧

1.1.1 多入口配置

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

// main1.js

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

// main2.js

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

index.html

<html>

  <body>

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

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

  </body>

</html>


webpack.config.js

module.exports ={

 entry:{

   bundle1: './main1.js',

   bundle2: './main2.js'

  },

 output:{

   filename: '[name].js'

  }

};

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

require('./app.css');


app.css

body{

  background-color: blue;

}


index.html

<html>

  <head>

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

  </head>

  <body>

    <h1>Hello World</h1>

  </body>

</html>


webpack.config.js

module.exports ={

 entry: './main.js',

 output:{

   filename: 'bundle.js'

  },

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

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"></script>

  </body>

</html>


webpack.config.js

module.exports ={

 entry: './main.js',

 output:{

   filename: 'bundle.js'

  },

 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) JS codes.

main.js

var longVariableName = 'Hello';

longVariableName += ' World';

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


index.html

<html>

  <body>

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

  </body>

</html>


webpack.config.js

var webpack = require('webpack');

var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

module.exports ={

  entry: './main.js',

  output:{

    filename: 'bundle.js'

  },

  plugins:[

    new uglifyJsPlugin({

      compress:{

        warnings: false

      }

    })

  ]

};


        After launching the server, main.js 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

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


webpack.config.js

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

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


module.exports ={

  entry: './main.js',

  output:{

    filename: 'bundle.js'

  },

  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

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

if (__DEV__) {

  document.write(new Date());

}


index.html

<html>

  <body>

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

  </body>

</html>


webpack.config.js

var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({

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

});

module.exports ={

  entry: './main.js',

  output:{

    filename: 'bundle.js'

  },

  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

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 should be separated from bundle.js and built into a single chunk file.

// a.js

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.

<html>

  <body>

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

  </body>

</html>


webpack.config.js

module.exports ={

  entry : './main.js',

  output:{

    filename : 'bundle.js'

  }

};


        Launch the server.

$ webpack-dev-server

        On the surface, you won't feel any differences. However, Webpack actually builds main.js and a.js into different chunks(bundle.js and 1.bundle.js), and loads 1.bundle.js from bundle.js 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

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

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


// To wait until a.js 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') tells Webpack to load a.js from another chunk.

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

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

var React = require('react');

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


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


// main2.jsx

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"></script>

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

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

  </body>

</html>


webpack.config.js

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

module.exports ={

  entry:{

    bundle1: './main1.jsx',

    bundle2: './main2.jsx'

  },

  output:{

    filename: '[name].js'

  },

  module:{

    loaders:[

    {

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

       exclude: /node_modules/,

       loader: 'babel-loader',

       query:{

         presets: ['es2015', 'react']

       }

    },

    ]

  },

 plugins:[

    new CommonsChunkPlugin('init.js')

  ]

}

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

var $ = require('jquery');

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


index.html

<html>

  <body>

    <h1></h1>

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

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

  </body>

</html>


webpack.config.js

var webpack = require('webpack');


module.exports ={

  entry:{

    app: './main.js',

    vendor: ['jquery'],

  },

  output:{

    filename: 'bundle.js'

  },

  plugins:[

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

  ]

};

    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

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


// webpack.config.js

var webpack = require('webpack');


module.exports ={

  entry:{

    app: './main.js'

  },

  output:{

    filename: 'bundle.js'

  },

  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 (official document).

        For example, we have a data.js.

var data = 'Hello World';

We can expose data as a global variable.

// webpack.config.js

module.exports ={

  entry: './main.jsx',

  output:{

    filename: 'bundle.js'

  },

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

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.

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

  ],

  output:{

    filename: 'bundle.js',

    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, and modify 'Hello World' into 'Hello Webpack'. Save it, and see what happened in the browser.

App.js

import React, { Component } from 'react';


export default class App extends Component{

  render() {

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

  }

}


index.js

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"></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的缺陷

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.org/guides/code-splitting/

(Good)webpack-demos

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 学习流程 参考文档:入门Webpack,看这篇就够了Webpack for React 一. 简单使用webpac...
    Jason_Zeng阅读 3,048评论 2 16
  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 10,933评论 0 21
  • webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert阅读 6,330评论 2 71
  • “春兰如美人,不采羞自献。时闻风露香,蓬艾深不见。”一一苏东坡 几年前去海南游玩,正好赶上当地举...
    巴根阅读 417评论 4 3
  • 在我孩提时,姥姥家院中间有两棵桃树,美艳的桃花根本入不了小孩子的眼睛,我眼巴眼望的是那又甜又脆的大桃。每到...
    浅一点不惊浓艳阅读 423评论 0 1