webpack2

作者: summer_1874 | 来源:发表于2017-11-20 11:17 被阅读0次

使用webpack构建项目

webpack核心概念

webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成少量的 bundle - 通常只有一个,由浏览器加载。

webpack

环境依赖

  • node

项目初始化

创建项目

创建一个webpack-demo项目并生成package.json文件。之后所有操作的根目录均为webpack-demo/

mkdir webpack-demo
cd webpack-doemo
npm init -f

引入webpack

npm install --save-dev webpack

项目初始结构分析

通常项目会分成三个运行环境:开发人员在本地跑的开发环境(dev)、测试人员用来做黑盒测试的测试环境(test)和线上运行的生产环境(production)
简单起见,本文只考虑开发环境(dev)和生产环境(prod),测试环境可以自行类比。


起步

webpack.config.js

//引入Node.js Path模块
const path = require('path);

module.exports = {
    entry:'./src/index.js',// string | object | array
    // 这里应用程序开始执行
    // webpack 开始打包
    output:{
        filename:'bundle.js',// string
    // 「入口分块(entry chunk)」的文件名模板(出口分块)
        path:path.resolve(__dirname,'dist') // string
    // 所有输出文件的目标路径
    // 必须是绝对路径(使用 Node.js 的 path 模块)
    }
}

path

  • 直接编译
        $ webpack
    
  • 基于NPM 脚本(NPM Scripts)
       $ npm run build
    
    • package.json

          {
          ...
          "scripts": {
              "build": "webpack"
          },
          ...
          }
      

管理资源

加载CSS

安装style-loadercss-loader

$ npm install --save-dev style-loader css-loader

src/index.js

+ impost './style.css';

webpack.config.js

const path = require('path');

module.exports = {
  entry:'./src/index.js',
  output:{
    filename:'bundle.js',
    path:path.resolve(__dirname,'dist')
  },
  module:{
    rules:[
      {
        test:/\.css$/,
        use:[
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
};

webpack 根据正则表达式,来确定应该查找哪些文件,并将其提供给指定的 loader。在这种情况下,以 .css 结尾的全部文件,都将被提供给 style-loader 和 css-loader。

加载图片

安装file-loader

$ npm install --seve-dev file-loader    

index.js

+ impost Icon from './icon.png';

webpack.config.js

...
module:{
    ...
    {
        test:/\.(png|svg|gif|jpg)$/,
        use:[
            'file-loader'
        ]
    }
}
...

加载字体,加载数据

管理输出

设定 HtmlWebpackPlugin

这个插件的作用是依据一个简单的index.html模板,生成一个自动引用你打包后的JS文件的新index.html。这在每次生成的js文件名称不同时非常有用(比如添加了hash值)。

$ npm install --save-dev html-webpack-plugin

webpack.config.js

...
plugins:[
    new HtmlWebpackPlugin({
      title: 'Output Management'
    })
  ],
...

清理 /dist 文件夹

一个webpack插件在构建之前删除/清理你的构建文件夹

$ npm install clean-webpack-plugin --save-dev

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
  entry: { 
    app: './src/index.js',
    print: './src/print.js'
  },
  plugins:[
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      title: 'Output Management'
    })
  ],
  output: {
    filename:'[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
};

开发

使用source map

对错误可追踪到源文件
webpack.config.js

module.exports = {
  ...
  devtoll:'inline-source-map'
  ...
}

现在在浏览器打开最终生成的 index.html 文件,点击按钮,并且在控制台查看显示的错误。错误应该如下:

 Uncaught ReferenceError: cosnole is not defined
    at HTMLButtonElement.printMe (print.js:2)

选择一个开发者

webpack 中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码:

  1. webpack's Watch Mode
  2. webpack-dev-server
  3. webpack-dev-middleware

多数情况使用webpack-dev-server

使用观察者模式

package.json

...
"scripts":{
  "watch":"webpack --watch",
  "build":"webpack"
}
...

使用wepack-dev-server

webpack-dev-server提供一个简单的web服务器,并且能实时重新加载(live reloading)。

$ npm install --save-dev webpack-dev-server

webpack.config.js

module.exports = {
  ...
  devServer:{
    contentBase:'./dist'
  }
  ...
}

以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。
package

...
"scripts":{
  "start":"webpack-dev-server --open"
}
...

使用webpack-dev-middleware

webpack-dev-middleware

模块热替换

允许在运行时更新各种模块,而无需进行完全刷新。

概念

启用HMR

webpack.config.js

const webpack = requier('webpack');
module.exports = {
  entry:{
    app:'./src/index.js'
  },
  devServer:{
    contentBase:'./dist',
    hot:true
  }
  ...
    plugins:[
      new webpack.NamedChunksPlugin(),
      new webpack.HotModuleReplacementPlugin()
      //热加载插件
    ]
  ...
}

index.js

...
+ if (module.hot) {
+   module.hot.accept('./print.js', function() {
+     console.log('Accepting the updated printMe module!');
+     printMe();
+   })
+ }

HMR 修改样式表

webpack.config.js

+   module: {
+     rules: [
+       {
+         test: /\.css$/,
+         use: ['style-loader', 'css-loader']
+       }
+     ]
+   },

index.js

+ import './styles.css';

Tree Shaking

用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 importexport

./src/mach.js

export function square(x){
  return x * x;
}
export function cube(x){
  return x * x * x;
}

index.js

import { cube } from "./math.js"

没有导出square,但是它仍被包含在编译后的文件中。

精简输出

$ npm install --save-dev uglifyjs-webpack-plugin

webpack.config.js

const UglifyjsPlugin = require('uglifyjs-webpack-plugin')

...
plugins:[
  new UglifyjsPlugin()
]
...

有复杂的依赖树的大型应用程序上运行时,tree shaking 或许会对 bundle 产生显著的体积优化。

生产环境构建

配置

开发环境(development)和生产环境(production)的构建目标差异很大。在开发环境中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力的 source maplocalhost server。而在生产环境中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的webpack配置。

安装

webpack-merge是专门用来处理webpack.config.js的配置文件分离的。它主要提供一个merge方法,来将各个分开的配置项给合并在一起

$ npm install --save-dev webpack-merge

project

  webpack-demo
  |- package.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /dist
  |- /src
    |- index.js
    |- math.js
  |- /node_modules

webpack.common.js

+ const path = require('path');
+ const CleanWebpackPlugin = require('clean-webpack-plugin');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+ module.exports = {
+   entry: {
+     app: './src/index.js'
+   },
+   plugins: [
+     new CleanWebpackPlugin(['dist']),
+     new HtmlWebpackPlugin({
+       title: 'Production'
+     })
+   ],
+   output: {
+     filename: '[name].bundle.js',
+     path: path.resolve(__dirname, 'dist')
+   }
+ };

webpack.dev.js

+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+   devtool: 'inline-source-map',
+   devServer: {
+     contentBase: './dist'
+   }
+ });

webpack.prod.js

+ const merge = require('webpack-merge');
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+   plugins: [
+     new UglifyJSPlugin()
+   ]
+ });

Minification

注意,虽然 UglifyJSPlugin 是代码压缩方面比较好的选择,但是还有一些其他可选择项。以下有几个同样很受欢迎的插件:

  • BabelMinifyWebpackPlugin
  • ClosureCompilerPlugin

source map

webpack.prod.js

  module.exports = merge(common, {
+   devtool: 'source-map',
    plugins: [
-     new UglifyJSPlugin()
+     new UglifyJSPlugin({
+       sourceMap: true
+     })
    ]
  })

避免在生产中使用 inline-***eval-***,因为它们可以增加 bundle 大小,并降低整体性能。

指定环境

CLI 替代选项

详情

代码分离

代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

有三种常用的代码分离方法:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
  • 动态导入:通过模块的内联函数调用来分离代码。

入口起点(entry points)

简单,直观。手动配置较多,并有些陷阱。

相关文章

  • webpack2教程续之DllPlugin

    本文承接webpack2教程、webpack2教程续之自动编译以及webpack2教程续之eslint检测,本文所...

  • webpack2教程续之eslint检测

    本文承接webpack2教程以及webpack2教程续之自动编译,本文所说的项目目录依旧是webpack2 在上两...

  • 详解 Webpack2 的那些路径

    Webpack2 中有很多涉及路径参数配置,若不知其所以然,很容易混淆出错。本文尽可能的汇集了 Webpack2 ...

  • webpack2学习

    webpack2学习 webpack2基本介绍 介绍 webpack和gulp一样是一个自动化的构建工具你不想做的...

  • webpack2教程续之自动编译

    本文承接上一篇webpack2教程,本文所说的项目目录依旧是webpack2 在上一篇中,我们搭建了基于webpa...

  • webpack1升级webpack2

    webpack2终于正式发布了。最近几天一直在调研webpack2的升级成本,因为公司的移动端使用的是webpac...

  • webpack2

    webpack2详解 1. 项目小工具 anywherenpm i -g anywhere //全局安装any...

  • webpack2

    webpack2 output hash和chunkhash,主要作用是用来去缓存hash ===> webpac...

  • webpack2

    使用webpack构建项目 webpack核心概念 webpack 是一个现代 JavaScript 应用程序的模...

  • react使用笔记

    代码分割require.ensure http://www.css88.com/doc/webpack2/gu...

网友评论

      本文标题:webpack2

      本文链接:https://www.haomeiwen.com/subject/eezmvxtx.html