加载中...

webpack进阶构建项目


1.理解webpack加载器

webpack的设计理念,所有资源都是“模块”,webpack内部实现了一套资源加载机制,这与Requirejs、Sea.js、Browserify等实现有所不同.

Webpack提供了一套加载器,比如css-loader,less-loader,style-loader,url-loader等,用于将不同的文件加载到js文件中,比如url-loader用于在js中加载png/jpg格式的图片文件,css/style loader用于加载css文件,less-loader加载器是将less编译成css文件;比如代码配置如下:

  1. module.exports = {
  2. entry: "./src/main.js",
  3. output: {
  4. filename: "build.js",
  5. path: __dirname + '/assets/',
  6. publicPath: "/assets/"
  7. },
  8. module: {
  9. loaders: [
  10. {test: /.css$/, loader: 'style!css'},
  11. {test: /.(png|jpg)$/, loader: 'url-loader?limit=8192'}
  12. ]
  13. }
  14. resolve: {
  15. extensions: ['', '.js', '.jsx'],
  16. //模块别名定义,方便后续直接引用别名,无须多写长长的地址
  17. alias: {
  18. a : 'js/assets/a.js', // 后面直接引用 require(“a”)即可引用到模块
  19. b : 'js/assets/b.js',
  20. c : 'js/assets/c.js'
  21. }
  22. },
  23. plugins: [commonsPlugin, new ExtractTextPlugin("[name].css")]
  24. }

module.loader: 其中test是正则表达式,对符合的文件名使用相应的加载器./.css$/会匹配 xx.css文件,但是并不适用于xx.sass或者xx.css.zip文件.
url-loader: 它会将样式中引用到的图片转为模块来处理; 配置信息的参数“?limit=8192”表示将所有小于8kb的图片都转为base64形式。
entry: 模块的入口文件。依赖项数组中所有的文件会按顺序打包,每个文件进行依赖的递归查找,直到所有模块都被打成包;
output:模块的输出文件,其中有如下参数:
filename: 打包后的文件名
path: 打包文件存放的绝对路径。
publicPath: 网站运行时的访问路径。
relolve.extensions: 自动扩展文件的后缀名,比如我们在require模块的时候,可以不用写后缀名的。
relolve.alias: 模块别名定义,方便后续直接引用别名,无须多写长长的地址
plugins 是插件项;

2.html-webpack-plugin学习

首先来看看项目的目录结构如下:

package.json 如下:

  1. {
  2. "name": "html-webpack-plugin",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "author": "",
  10. "license": "ISC",
  11. "devDependencies": {
  12. "html-webpack-plugin": "^2.19.0",
  13. "webpack": "^1.13.1"
  14. }
  15. }

运行命令 npm install 把依赖包加载出来;

接着在 webpack.config.js配置如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. console.log(SRC_PATH)
  8. module.exports = {
  9. entry: SRC_PATH + "/js/index.js",
  10. //输出的文件名 合并以后的js会命名为index.js
  11. output: {
  12. path: BUILD_PATH,
  13. filename: 'index.js'
  14. },
  15. //添加我们的插件 会自动生成一个html文件
  16. plugins: [
  17. new HtmlwebpackPlugin({
  18. title: 'Hello World app'
  19. })
  20. ]
  21. };

在项目中的根目录下 运行 webpack 就能生成buid文件夹了,里面会自动生成 两个文件 index.html和index.js文件;
index.html代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World app</title>
  6. </head>
  7. <body>
  8. <script type="text/javascript" src="index.js"></script></body>
  9. </html>

标题title就是我们配置上的;
且合并了依赖的js文件;我们可以直接在本地访问index.html 可以看到能打印出依赖的文件js代码了;可以看到可以解决依赖的问题;
html-webpack-plugin 还支持如下配置:
title: 用于生成的HTML文件的标题。
filename: 用于生成的HTML文件的名称,默认是index.html。你可以在这里指定子目录。
template: 模板文件路径,支持加载器,比如 html!./index.html
inject: true | 'head' | 'body' | false ,注入所有的资源到特定的 template 或者 templateContent 中,如果设置为 true
或者 body,所有的 javascript 资源将被放置到 body 元素的底部,'head' 将放置到 head 元素中。
favicon: 添加特定的 favicon 路径到输出的 HTML 文件中。
minify:{ //压缩HTML文件
removeComments:true, //移除HTML中的注释
collapseWhitespace:true //删除空白符与换行符
}
hash: true | false, 如果为 true, 将添加一个唯一的 webpack 编译 hash 到所有包含的脚本和 CSS 文件,对于解除 cache 很有用。
cache: true | false,如果为 true, 这是默认值,仅仅在文件修改之后才会发布文件。
showErrors: true | false, 如果为 true, 这是默认值,错误信息会写入到 HTML 页面中
chunks: 允许只添加某些块 (比如,仅仅 unit test 块)
chunksSortMode: 允许控制块在添加到页面之前的排序方式,支持的值:'none' | 'default' | {function}-default:'auto'
excludeChunks: 允许跳过某些块,(比如,跳过单元测试的块)

比如我现在webpack.config.js配置改为如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. console.log(SRC_PATH)
  8. module.exports = {
  9. entry: SRC_PATH + "/js/index.js",
  10. //输出的文件名 合并以后的js会命名为index.js
  11. output: {
  12. path: BUILD_PATH,
  13. filename: 'index.js'
  14. },
  15. //添加我们的插件 会自动生成一个html文件
  16. plugins: [
  17. new HtmlwebpackPlugin({
  18. title: 'Hello World app',
  19. filename: '1.0.0/home.html',
  20. inject: true,
  21. hash: true
  22. })
  23. ]
  24. };

然后再在命令行中继续运行webpack命令,可以看到在build下会生成2个目录 第一个是build/1.0.1/home.html; 第二个是 build/index.js
再来看下home.html代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World app</title>
  6. </head>
  7. <body>
  8. <script type="text/javascript" src="../index.js?d03211ff5e0251af224d"></script></body>
  9. </html>

可以看到设置 hash为true js的后缀会自动加一个hash编码,对于页面解决缓存很有用;

生成多个 HTML 文件
通过在配置文件中添加多次这个插件,来生成多个 HTML 文件。
webpack.config.js代码如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. console.log(SRC_PATH)
  8. module.exports = {
  9. entry: SRC_PATH + "/js/index.js",
  10. //输出的文件名 合并以后的js会命名为index.js
  11. output: {
  12. path: BUILD_PATH,
  13. filename: 'index.js'
  14. },
  15. //添加我们的插件 会自动生成一个html文件
  16. plugins: [
  17. new HtmlwebpackPlugin(),
  18. new HtmlwebpackPlugin({
  19. title: 'Hello World app',
  20. filename: 'app1/home.html',
  21. template: 'src/html/index.html',
  22. inject: true,
  23. hash: true
  24. })
  25. ]
  26. };

官网可以看这里 https://www.npmjs.com/package/html-webpack-plugin
也可以在配置项 加上minify选项 压缩HTML文件;代码如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. console.log(SRC_PATH)
  8. module.exports = {
  9. entry: SRC_PATH + "/js/index.js",
  10. //输出的文件名 合并以后的js会命名为index.js
  11. output: {
  12. path: BUILD_PATH,
  13. filename: 'index.js'
  14. },
  15. //添加我们的插件 会自动生成一个html文件
  16. plugins: [
  17. new HtmlwebpackPlugin({
  18. title: 'Hello World app',
  19. minify:{ //压缩HTML文件
  20. removeComments:true, //移除HTML中的注释
  21. collapseWhitespace:true //删除空白符与换行符
  22. }
  23. })
  24. ]
  25. };

查看html生成后的文件可以看到已经被压缩了;

3.压缩js与css

webpack已经内嵌了uglifyJS来完成对JS与CSS的压缩混淆,无需引用额外的插件。
压缩代码如下:

  1. new webpack.optimize.UglifyJsPlugin({ //压缩代码
  2. compress: {
  3. warnings: false
  4. },
  5. except: ['$super', '$', 'exports', 'require'] //排除关键字
  6. })

这里需要注意的是压缩的时候需要排除一些关键字,不能混淆,比如$或者require,如果混淆的话就会影响到代码的正常运行。
webpack.config.js代码改为如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var webpack = require("webpack");
  4. //定义了一些文件夹的路径
  5. var ROOT_PATH = path.resolve(__dirname);
  6. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  7. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  8. console.log(SRC_PATH)
  9. module.exports = {
  10. entry: {
  11. 'index' : SRC_PATH + "/js/index.js"
  12. },
  13. //输出的文件名 合并以后的js会命名为index.js
  14. output: {
  15. path: BUILD_PATH + '/js/',
  16. filename: '[name].js'
  17. },
  18. //添加我们的插件 会自动生成一个html文件
  19. plugins: [
  20. new HtmlwebpackPlugin({
  21. title: 'Hello World app',
  22. minify:{ //压缩HTML文件
  23. removeComments:true, //移除HTML中的注释
  24. collapseWhitespace:true //删除空白符与换行符
  25. }
  26. }),
  27. new webpack.optimize.UglifyJsPlugin({ //压缩代码
  28. compress: {
  29. warnings: false
  30. },
  31. except: ['$super', '$', 'exports', 'require'] //排除关键字
  32. })
  33. ]
  34. };

继续运行下webpack可以看到js已经被压缩了;注意:但是貌似对es6的语法不能压缩~

4.理解less-loader加载器的使用

 我们先来理解下less-loader加载器,其他的sass-loader也是一个意思,less-loader加载器是把css代码转化到style标签内,

动态插入到head标签内;我们先来看看我项目的结构如下:

src/html/index.html代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  5. <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"/>
  6. <meta content="yes" name="apple-mobile-web-app-capable" />
  7. <meta content="black" name="apple-mobile-web-app-status-bar-style" />
  8. <meta content="telephone=no" name="format-detection" />
  9. <meta content="email=no" name="format-detection" />
  10. <meta name="description" content="基于webpack的前端工程化开发解决方案探索"/>
  11. <title>动态生成html的实践</title>
  12. </head>
  13. <body>
  14. <div>hello webpack</div>
  15. </body>
  16. </html>

现在我想通过html-webpack-plugin插件动态生成 html页面及引入index.js 和 生成 index.js文件;

webpack.config.js代码配置如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. module.exports = {
  8. entry: SRC_PATH + "/js/index.js",
  9. output: {
  10. filename: "build.js",
  11. path: BUILD_PATH
  12. },
  13. module: {
  14. loaders: [
  15. //.css 文件使用 style-loader 和 css-loader 来处理
  16. {
  17. test: /\.less$/,
  18. loader: "style!css!less"
  19. }
  20. ]
  21. },
  22. resolve: {
  23. extensions: ['', '.js', '.jsx']
  24. },
  25. plugins: [
  26. new HtmlwebpackPlugin({
  27. title: 'Hello World app',
  28. filename: 'index.html',
  29. template: 'src/html/index.html',
  30. inject: true,
  31. hash: true
  32. })
  33. ]
  34. };

在项目的根目录运行webpack,即可动态生成html文件和js文件,打开生成后的index.html即可看到css生效了,且css被动态内链到head标签内了;

其中less/main.less 文件如下代码:

@color: red;

body {
    background:@color;
}
如上可以看到less文件得到编译,且动态插入到head标签内;

5.理解babel-loader加载器

babel-loader加载器能将ES6的代码转换成ES5代码,我们需要安装babel-loader
执行命令:npm install babel-loader --save-dev
因此现在需要在webpack.config.js 加入babel-loader的加载器即可;如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. //定义了一些文件夹的路径
  4. var ROOT_PATH = path.resolve(__dirname);
  5. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  6. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  7. module.exports = {
  8. entry: SRC_PATH + "/js/index.js",
  9. output: {
  10. filename: "build.js",
  11. path: BUILD_PATH
  12. },
  13. module: {
  14. loaders: [
  15. //.css 文件使用 style-loader 和 css-loader 来处理
  16. {
  17. test: /\.less$/,
  18. loader: "style!css!less"
  19. },
  20. {
  21. test: /\.js$/,
  22. loader: 'babel'
  23. }
  24. ]
  25. },
  26. resolve: {
  27. extensions: ['', '.js', '.jsx']
  28. },
  29. plugins: [
  30. new HtmlwebpackPlugin({
  31. title: 'Hello World app',
  32. filename: 'index.html',
  33. template: 'src/html/index.html',
  34. inject: true,
  35. hash: true
  36. })
  37. ]
  38. };

a.js 假如是ES6的语法;比如如下一句代码:
// es6的语法
let LOADER = true;
module.exports = LOADER;

现在在index.js代码如下:
var aModule = require('../less/main.less');
console.log(aModule);

// es6的语法
var aMoudle = require('./a');
console.log(aMoudle);

可以看到打印 aMoudle的值为true;说明可以正确的解析了;

6.理解 extract-text-webpack-plugin(独立打包样式文件)

执行安装命令:
sudo npm install extract-text-webpack-plugin
然后再webpack.config.js 加入加载器配置项如下代码:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. //定义了一些文件夹的路径
  5. var ROOT_PATH = path.resolve(__dirname);
  6. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  7. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  8. module.exports = {
  9. entry: SRC_PATH + "/js/index.js",
  10. output: {
  11. filename: "build.js",
  12. path: BUILD_PATH
  13. },
  14. module: {
  15. loaders: [
  16. //.css 文件使用 style-loader 和 css-loader 来处理
  17. {
  18. test: /\.less$/,
  19. loader: ExtractTextPlugin.extract(
  20. 'css?sourceMap!' +
  21. 'less?sourceMap'
  22. )
  23. },
  24. {
  25. test: /\.js$/,
  26. loader: 'babel'
  27. }
  28. ]
  29. },
  30. resolve: {
  31. extensions: ['', '.js', '.jsx']
  32. },
  33. plugins: [
  34. // 内联css提取到单独的styles的css
  35. new ExtractTextPlugin("index.css"),
  36. new HtmlwebpackPlugin({
  37. title: 'Hello World app',
  38. filename: 'index.html',
  39. template: 'src/html/index.html',
  40. inject: true,
  41. hash: true
  42. })
  43. ]
  44. };

在项目的根目录运行 webpack 即可生效;会在build目录下 生成 index.css文件,且在打包后的index.html会自动引入link标签的css;
如下所示:

如果页面上有多个less文件或者css文件的话,也可以通过 @import 动态导入;如下在main.less 引入 a.less代码如下:
@import './a.less';
a.less 是和main.less 同级目录下的;

7.webpack打包多个资源文件

 我们在开发页面的时候,有时候需要有多个入口文件,做到文件是按需加载,这样就可以使用缓存提升性能;

只需要像如下编码即可:

  1. module.exports = {
  2. entry: {
  3. "main": "./src/a.js",
  4. "index": "./src/index.js"
  5. },
  6. output: {
  7. filename: "[name].js"
  8. }
  9. };

webpack.config.js代码如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. var webpack = require("webpack");
  5. //定义了一些文件夹的路径
  6. var ROOT_PATH = path.resolve(__dirname);
  7. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  8. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  9. module.exports = {
  10. entry: {
  11. "a": SRC_PATH + "/js/a.js",
  12. "index": SRC_PATH + "/js/index.js",
  13. },
  14. output: {
  15. filename: "[name].js",
  16. path: BUILD_PATH
  17. },
  18. module: {
  19. loaders: [
  20. //.css 文件使用 style-loader 和 css-loader 来处理
  21. {
  22. test: /\.less$/,
  23. loader: ExtractTextPlugin.extract(
  24. 'css?sourceMap!' +
  25. 'less?sourceMap'
  26. )
  27. },
  28. {
  29. test: /\.js$/,
  30. loader: 'babel'
  31. }
  32. ]
  33. },
  34. resolve: {
  35. extensions: ['', '.js', '.jsx']
  36. },
  37. plugins: [
  38. // 内联css提取到单独的styles的css
  39. new ExtractTextPlugin("index.css"),
  40. new HtmlwebpackPlugin({
  41. title: 'Hello World app',
  42. filename: 'index.html',
  43. template: 'src/html/index.html',
  44. inject: true,
  45. hash: true
  46. }),
  47. new webpack.optimize.UglifyJsPlugin({ //压缩代码
  48. compress: {
  49. warnings: false
  50. },
  51. except: ['$super', '$', 'exports', 'require'] //排除关键字
  52. })
  53. ]
  54. };

8.webpack对图片的打包

 图片是 url-loader来加载的,我们既可以在css文件里url的属性;

首先先安装 url-loader插件;
sudo npm install --save-dev url-loader

首先在less文件里面加入如下代码:
@color: red;
body {
background:@color;
background:url('../images/1.png') no-repeat;
}
在index.js里面加入如下代码:
var aModule = require('../less/main.less');
console.log(aModule);

在webpack.config.js代码配置加入如下:
{
test: /.(png|jpg)$/,
loader: 'url?limit=8192'
}
webpack.config.js所有代码如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. var webpack = require("webpack");
  5. //定义了一些文件夹的路径
  6. var ROOT_PATH = path.resolve(__dirname);
  7. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  8. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  9. module.exports = {
  10. entry: {
  11. "a": SRC_PATH + "/js/a.js",
  12. "index": SRC_PATH + "/js/index.js",
  13. },
  14. output: {
  15. filename: "[name].js",
  16. path: BUILD_PATH
  17. },
  18. module: {
  19. loaders: [
  20. //.css 文件使用 style-loader 和 css-loader 来处理
  21. {
  22. test: /\.less$/,
  23. loader: ExtractTextPlugin.extract(
  24. 'css?sourceMap!' +
  25. 'less?sourceMap'
  26. )
  27. },
  28. {
  29. test: /\.js$/,
  30. loader: 'babel'
  31. },
  32. {
  33. test: /.(png|jpg)$/,
  34. loader: 'url?limit=8192&name=img/[hash:8].[name].[ext]'
  35. }
  36. ]
  37. },
  38. resolve: {
  39. extensions: ['', '.js', '.jsx']
  40. },
  41. plugins: [
  42. // 内联css提取到单独的styles的css
  43. new ExtractTextPlugin("index.css"),
  44. new HtmlwebpackPlugin({
  45. title: 'Hello World app',
  46. filename: 'index.html',
  47. template: 'src/html/index.html',
  48. inject: true,
  49. hash: true
  50. }),
  51. new webpack.optimize.UglifyJsPlugin({ //压缩代码
  52. compress: {
  53. warnings: false
  54. },
  55. except: ['$super', '$', 'exports', 'require'] //排除关键字
  56. })
  57. ]
  58. };

因此在项目的根目录运行webpack后,即可,然后会生成index.css文件代码如下:
body{background:red;background:url(8eaebaa98ed1fe64bbf9f0f954b2b230.png) no-repeat}
因此可以看到会动态转换成base64编码;

9.学习web-dev-server 创建服务器及动态监听css及js文件的改变;

 在webpack中,我们经常使用webpack-dev-server作为开发服务器,用于实时监听和打包编译静态资源,这样每当我们修改js、css等等文件时,客户端(如浏览器等)能够自动刷新页面,展示实时的页面效果。

webpack-dev-server只监听webpack.config.js中entry入口下文件(如js、css等等)的变动,

只有这些文件的变动才会触发实时编译打包与页面刷新,但是html文件更改后保存不能监听新内容到,但是对于开发影响不大,我们在编写css文件
或者js文件的时候保存后,会自动刷新页面,所以html页面也会自动更新到;

首先需要进入我们的项目的根目录下需要安装webpack-dev-server 安装命令如下:
sudo npm install --save-dev webpack-dev-server

首先我项目的目录如下:

安装完成后,需要在webpack.config.js文件配置下;如下代码:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. var webpack = require("webpack");
  5. //定义了一些文件夹的路径
  6. var ROOT_PATH = path.resolve(__dirname);
  7. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  8. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  9. module.exports = {
  10. entry: {
  11. "a": SRC_PATH + "/js/a.js",
  12. "index": SRC_PATH + "/js/index.js"
  13. },
  14. output: {
  15. filename: "/js/[name].js",
  16. path: BUILD_PATH
  17. },
  18. module: {
  19. loaders: [
  20. //.css 文件使用 style-loader 和 css-loader 来处理
  21. {
  22. test: /\.less$/,
  23. loader: ExtractTextPlugin.extract(
  24. 'css?sourceMap!' +
  25. 'less?sourceMap'
  26. )
  27. },
  28. {
  29. test: /\.js$/,
  30. loader: 'babel'
  31. },
  32. {
  33. test: /.(png|jpg)$/,
  34. loader: 'url?limit=8192&name=images/[hash:8].[name].[ext]'
  35. }
  36. ]
  37. },
  38. resolve: {
  39. extensions: ['', '.js', '.jsx']
  40. },
  41. plugins: [
  42. // 内联css提取到单独的styles的css
  43. new ExtractTextPlugin("/css/index.css"),
  44. new HtmlwebpackPlugin({
  45. title: 'Hello World app',
  46. filename: 'html/index.html',
  47. template: 'src/html/index.html',
  48. inject: true,
  49. hash: true
  50. }),
  51. new webpack.optimize.UglifyJsPlugin({ //压缩代码
  52. compress: {
  53. warnings: false
  54. },
  55. except: ['$super', '$', 'exports', 'require'] //排除关键字
  56. })
  57. ]
  58. };

接着需要创建一个webpack-config-dev.js文件,该文件的作用是创建本地服务器,及实时监听css及js文件的改变;代码如下:

  1. var path = require('path')
  2. var webpack = require('webpack');
  3. var HtmlwebpackPlugin = require('html-webpack-plugin');
  4. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  5. module.exports = {
  6. devtool: 'cheap-eval-source-map',
  7. entry: [
  8. 'webpack-dev-server/client?http://127.0.0.1:8080',
  9. 'webpack/hot/dev-server',
  10. './src/js/index',
  11. './src/js/a',
  12. './src/less/main.less'
  13. ],
  14. output: {
  15. path: path.join(__dirname, 'build'),
  16. filename: '/js/[name].js'
  17. },
  18. plugins: [
  19. new webpack.HotModuleReplacementPlugin(),
  20. new HtmlwebpackPlugin({
  21. title: 'Hello World app',
  22. filename: 'html/index.html',
  23. template: 'src/html/index.html',
  24. inject: true,
  25. hash: true
  26. }),
  27. new ExtractTextPlugin("index.css")
  28. ],
  29. module: {
  30. loaders: [
  31. //.css 文件使用 style-loader 和 css-loader 来处理
  32. {
  33. test: /\.less$/,
  34. loader: ExtractTextPlugin.extract(
  35. 'css?sourceMap!' +
  36. 'less?sourceMap'
  37. )
  38. },
  39. {
  40. test: /\.js$/,
  41. loader: 'babel'
  42. },
  43. {
  44. test: /.(png|jpg)$/,
  45. loader: 'url?limit=8192&name=images/[hash:8].[name].[ext]'
  46. }
  47. ]
  48. },
  49. devServer: {
  50. contentBase: './dist',
  51. hot: true
  52. }
  53. }

上面只是在开发环境配置的;我们还需要一个线上环境,进行打包,我们还需要使用一个线上环境打包的配置;我们可以新建一个叫webpack.config.prod.js文件; 该文件的配置用于在生产环境的打包;配置代码如下:

  1. var path = require('path')
  2. var webpack = require('webpack');
  3. var HtmlwebpackPlugin = require('html-webpack-plugin');
  4. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  5. module.exports = {
  6. devtool: 'source-map',
  7. entry: ['./src/js/index','./src/js/a'],
  8. output: {
  9. path: path.join(__dirname, 'build'),
  10. filename: '/js/[name].js'
  11. },
  12. plugins: [
  13. new webpack.HotModuleReplacementPlugin(),
  14. new HtmlwebpackPlugin({
  15. title: 'Hello World app',
  16. filename: 'html/index.html',
  17. template: 'src/html/index.html',
  18. inject: true,
  19. hash: true
  20. }),
  21. new ExtractTextPlugin("index.css")
  22. ],
  23. module: {
  24. loaders: [
  25. //.css 文件使用 style-loader 和 css-loader 来处理
  26. {
  27. test: /\.less$/,
  28. loader: ExtractTextPlugin.extract(
  29. 'css?sourceMap!' +
  30. 'less?sourceMap'
  31. )
  32. },
  33. {
  34. test: /\.js$/,
  35. loader: 'babel'
  36. },
  37. {
  38. test: /.(png|jpg)$/,
  39. loader: 'url?limit=8192&name=images/[hash:8].[name].[ext]'
  40. }
  41. ]
  42. }
  43. }

package.json文件代码如下:

  1. {
  2. "name": "html-webpack-plugin",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "build": "webpack --config webpack.config.prod.js",
  8. "dev": "webpack-dev-server --config webpack.config.dev.js"
  9. },
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "babel-core": "^6.9.1",
  14. "babel-loader": "^6.2.4",
  15. "css-loader": "^0.23.1",
  16. "file-loader": "^0.8.5",
  17. "html-webpack-plugin": "^2.19.0",
  18. "http-server": "^0.9.0",
  19. "less": "^2.7.1",
  20. "less-loader": "^2.2.3",
  21. "react-hot-loader": "^1.3.0",
  22. "style-loader": "^0.13.1",
  23. "url-loader": "^0.5.7",
  24. "webpack": "^1.13.1",
  25. "webpack-dev-server": "^1.14.1"
  26. }
  27. }

接着我们先运行webpack,就可以在项目的根目录下生成build文件夹了;
如下图所示:

为了更方便运行我们在package.json添加如下代码:
"scripts": {
     "build": "webpack --config webpack.config.prod.js",
     "dev": "webpack-dev-server --config webpack.config.dev.js"
}
因此如果在开发环境的话,可以运行 npm run dec; 如果是线上的环境,可以运行 npm run build 即可;
但是当我们运行 npm run dev的时候 会出现如下错误:

这是因为 默认centos的 hosts 会把本地 127.0.0.1 localhost 注释掉; 我们可以在我们hosts文件夹下 多加一句
127.0.0.1 localhost
即可;
我们可以参考 https://github.com/Unitech/pm2/issues/324

webpack-dev-server git上的地址: https://github.com/tugenhua0707/webpack-dev-server 

10.assets-webpack-plugin插件解决html文件的版本号的问题;

 我们上面学习过 html-webpack-plugin 这个插件,它可以自动添加版本号,但是对于很多前端开发的时候,我们的html页面是放在服务器端那边的部署,架构是前后端分离,因为html是在后台的,所以根本操作不了html,也不应该耦合。 

我们可以通过webpack的 assets-webpack-plugin 插件生成一个记录了版本号的文件;详细的可以看官网地址是: https://www.npmjs.com/package/assets-webpack-plugin;
首先我们需要在我们的项目下安装该插件:安装命令如下:
npm install assets-webpack-plugin --save-dev
只需要在webpack.config.json添加如下代码:

  1. // 部分代码
  2. var AssetsPlugin = require('assets-webpack-plugin');
  3. new AssetsPlugin({
  4. filename: 'build/webpack.assets.js',
  5. processOutput: function (assets) {
  6. return 'window.WEBPACK_ASSETS = ' + JSON.stringify(assets);
  7. }
  8. })

我们现在来在webpack.config.js配置项如下

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. //定义了一些文件夹的路径
  5. var ROOT_PATH = path.resolve(__dirname);
  6. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  7. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  8. var AssetsPlugin = require('assets-webpack-plugin');
  9. module.exports = {
  10. entry: {
  11. "a": SRC_PATH + "/js/a.js",
  12. "index": SRC_PATH + "/js/index.js"
  13. },
  14. output: {
  15. path: path.join(__dirname, "build"),
  16. filename: "js/[name]-[chunkhash:8].js",
  17. },
  18. module: {
  19. loaders: [
  20. //.css 文件使用 style-loader 和 css-loader 来处理
  21. {
  22. test: /\.less$/,
  23. loader: ExtractTextPlugin.extract(
  24. 'css?sourceMap!' +
  25. 'less?sourceMap'
  26. )
  27. },
  28. {
  29. test: /\.js$/,
  30. loader: 'babel'
  31. }
  32. ]
  33. },
  34. resolve: {
  35. extensions: ['', '.js', '.jsx']
  36. },
  37. plugins: [
  38. // 内联css提取到单独的styles的css
  39. new ExtractTextPlugin("css/index.css"),
  40. new HtmlwebpackPlugin({
  41. title: 'Hello World app',
  42. filename: 'html/index.html',
  43. template: 'src/html/index.html',
  44. inject: true
  45. }),
  46. new AssetsPlugin({
  47. filename: 'build/webpack.assets.js',
  48. processOutput: function (assets) {
  49. return 'window.WEBPACK_ASSETS = ' + JSON.stringify(assets);
  50. }
  51. })
  52. ]
  53. };

然后运行webpack命令进行打包后 如下图所示:

可以看到在我们的build目录下的js文件生成a和index带有版本号的js文件,在build目录下还生成了一个 webpack.assets.js文件;该文件
代码如下:
window.WEBPACK_ASSETS = {"a":{"js":"js/a-a7cbb4daad866656445a.js"},
"index":{"js":"js/index-a7cbb4daad866656445a.js"}}

因此我们可以把该webpack.assets.js文件让开发在页面上引入即可;
<script src="build/webpack.assets.js?v=' + Math.random() + '"></script>
<script src="' + window.WEBPACK_ASSETS['a'].js + '"></script>
<script src="' + window.WEBPACK_ASSETS['index'].js + '"></script>

我们继续看 chunkhash:8 的含义:其中8是指hash长度为8,默认是16。加上chunkhash就可以缓存文件;因为每次打包的时候都会自动生成
版本号,但是有些文件并没有修改的话,我们不需要更改版本号,我们想直接从缓存里面读取,对于更改的文件我们需要从服务器下载,对于
这样的 chunkhash 可以解决;比如如下两次的版本号:
window.WEBPACK_ASSETS = {"a":{"js":"js/a-ac4c0d24.js"},"index":{"js":"js/index-7c5ec642.js"}}
当我更改index.js代码的时候 a.js代码没有更改的话;变成如下:
window.WEBPACK_ASSETS = {"a":{"js":"js/a-ac4c0d24.js"},"index":{"js":"js/index-9a2fec25.js"}}

11.webpack关于同步加载和异步加载的问题

 使用webpack打包,直接使用require模块可以解决模块的依赖的问题,

  对于直接require模块,WebPack的做法是把依赖的文件都打包在一起,造成文件很臃肿。即是同步加载,同步的代码会被合成并且打包在一起;
而 异步加载的代码会被分片成一个个chunk,在需要该模块时再加载,即按需加载,同步加载过多代码会造成文件过大影响加载速度;
异步过多则文件太碎,造成过多的Http请求,同样影响加载速度。这要看开发者自己权衡下;
同步加载的写法如下:
var aModule =
require('./a');
异步加载的写法如下:
require.ensure(['./a'],function(require){
     var aModule = require('./a');
},'tips');
使用 require.ensure 可以解决异步加载模块的文件;如上代码,如果ensure不指定第三个参数的话(tips),那么webpack会随机生成一个数字
作为模块名,我们指定第三个参数为tips;那说明生成后的模块名叫tips.js;
这时候我们需要使用到webpack.config.js中的output选项需要加一个配置项:chunkFilename: "[name].min.js"

下面可以先来理解下 webpack中的output.filename 和output.chunkFilename
比如如下配置代码:

  1. {
  2. entry: {
  3. "index": "pages/index.jsx"
  4. },
  5. output: {
  6. filename: "[name].min.js",
  7. chunkFilename: "[name].min.js"
  8. }
  9. }

filename应该比较好理解,就是对应于entry里面生成出来的文件名;即会生成 index.min.js文件名;
chunkname的理解是在按需加载(异步)模块的时候,这样的文件是没有被列在entry中的,如使用CommonJS的方式异步加载模块时候会使用到;
比如如上这要异步加载一个a.js模块,代码如下:
require.ensure(['./a'],function(require){
    var aModule = require('./a');
},'tips');
指定第三个参数为tips,因此配合output中的 chunkFilename, 即会生成 tips.min.js了;
比如如下所示:

tips.js代码如下:

  1. webpackJsonp([1],[
  2. /* 0 */,
  3. /* 1 */
  4. /***/ function(module, exports) {
  5. /*
  6. // es6的语法
  7. let LOADER = true;
  8. module.exports = LOADER;
  9. */
  10.  
  11. function a() {
  12. console.log("a");
  13. console.log(11);
  14. console.log(222444);
  15. }
  16. a();
  17. /***/ }
  18. ]);

会通过 webpackJsonp 模块包装一下;接着我们在index.js代码看下,它使如何被调用的;如下片段代码:
__webpack_require__.e/* nsure */(1, function (require) {
     var aModule = __webpack_require__(1);
});
即可引用的到;也就是说如果a.js模块有1000+行代码,不会被包含到index.js代码内,但是index.js代码有a.js代码模块的引用;
可以加载到a.js代码的内容;
下面是我的webpack.config.js代码配置如下:

  1. var path = require('path');
  2. var HtmlwebpackPlugin = require('html-webpack-plugin');
  3. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. //定义了一些文件夹的路径
  5. var ROOT_PATH = path.resolve(__dirname);
  6. var SRC_PATH = path.resolve(ROOT_PATH, 'src');
  7. var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
  8. var AssetsPlugin = require('assets-webpack-plugin');
  9. module.exports = {
  10. entry: {
  11. "index": SRC_PATH + "/js/index.js"
  12. },
  13. output: {
  14. path: path.join(__dirname, "build"),
  15. filename: "js/[name]-[chunkhash:8].js",
  16. chunkFilename: "js/[name]-[chunkhash:8].js"
  17. },
  18. module: {
  19. loaders: [
  20. //.css 文件使用 style-loader 和 css-loader 来处理
  21. {
  22. test: /\.less$/,
  23. loader: ExtractTextPlugin.extract(
  24. 'css?sourceMap!' +
  25. 'less?sourceMap'
  26. )
  27. },
  28. {
  29. test: /\.js$/,
  30. loader: 'babel'
  31. }
  32. ]
  33. },
  34. resolve: {
  35. extensions: ['', '.js', '.jsx']
  36. },
  37. plugins: [
  38. // 内联css提取到单独的styles的css
  39. new ExtractTextPlugin("css/index.css"),
  40. new HtmlwebpackPlugin({
  41. title: 'Hello World app',
  42. filename: 'html/index.html',
  43. template: 'src/html/index.html',
  44. inject: true
  45. }),
  46. new AssetsPlugin({
  47. filename: 'build/webpack.assets.js',
  48. processOutput: function (assets) {
  49. return 'window.WEBPACK_ASSETS = ' + JSON.stringify(assets);
  50. }
  51. })
  52. ]
  53. };

index.js代码异步调用a.js模块的代码如下:
require.ensure(['./a'],function(require){
    var aModule = require('./a');
},'tips');
更多的配置项 看官网 http://webpack.github.io/docs/code-splitting.html


还没有评论.