如何配置webpack(学习总结)

来源:互联网 发布:c语言内容有多少 编辑:程序博客网 时间:2024/05/19 11:35

什么是webpack

WebPack可以看做是模块打包机:它可以分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

webpack与Grunt和Gulp的区别

webpack与Grunt和Gulp不同,它本身并不是一个打包工具,但它具有可以替代它们的优势。

Grunt和Gulp的工作模式:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。
Gulp和Grunt工作流

webpack的工作模式:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件(通过跟踪js文件中的require和import语句),使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
webpack工作流

开始使用Webpack

Webpack可以通过npm来进行安装。

//全局安装
npm install -g webpack
//安装到项目依赖
npm install –save-dev webpack

示例项目

首先新建一个空文件夹(webpack sample project),并创建一个package.json文件。package.json可以通过npm命令来进行初始化:

npm init

输入这个命令后,终端会询问一系列诸如项目名称、描述、作者等信息。但是如果不需要将你的项目发布到npm上,这些信息都是无关紧要的,直接默认即可。
接下来安装webpack,将其作为你的项目依赖包:

npm install –save-dev webpack

然后回到之前的空文件夹,部署我们的项目结构。首先创建两个文件夹:app文件夹用于存放原始数据和JavaScript模块,public文件夹用于供浏览器读取的文件(包括使用webpack打包生成的js文件以及一个index.html文件)。接下来创建三个文件:index.html,位于public文件夹下,两个js文件(main.js和Greeter.js)放在app文件夹下。最终的项目结构如下图:
项目结构

在index.html中写入最基本的HTML代码,它的唯一作用是用来加载打包后的JavaScript文件。

<!-- index.html --><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Webpack Sample Project</title></head><body>    <div id="root"></div>    <script src="bundle.js"></script></body></html>

接下来就可以专注于写js文件了。Greeter.js中是一个简单的函数,它返回一个带有问候信息的新的HTML元素。main.js文件将会导入Greeter并将其返回的元素插入到页面中。

//main.jsvar greeter = require("./Greeter,js");document.getElementById('root').appendChild(greeter());//Greeter.jsmodule.exports = function() {    var greet = document.createElement('div');    greet.textContent = "Hi there and greetings!";    return greet;}

正式开始使用webpack

最基本的webpack命令行语法是webpack {entry file} {destination for bundled file}。Webpack需要你指定一个入口文件,webpack将会自动识别项目所依赖的其他文件。如果你没有在全局安装webpack的话,在终端使用该命令需要额外指出webpack在node_modules文件夹下的位置:

node_modules/.bin/webpack app/main.js public/bundle.js

运行结果如下图:

可以看到webpack同时编译了main.js和Greeter.js文件,现在在浏览器中打开index.html,将会看到下面的内容:

定义配置文件

Webpack有很多不同的高级的功能,它可以通过利用loaders和plugins来转换加载的模块。尽管在命令行中可以使用webpack的所有选项,但是这个过程很慢,而且容易出错。更好的方法是定义一个配置文件,它是一个js模块,你可以把所有的与打包相关的信息都放在里面。
首先在文件夹根目录下创建一个webpack.config.js文件,该文件中必须包含入口文件和打包后文件的存放路径。

//webpack.confgi.jsmodule.exports = {    entry: __dirname + "/app/main.js", //唯一入口文件    output: {        path: __dirname + "/public", //打包后文件的存放路径        filename: "bundle.js" //打包后文件的名称    }}

现在可以在终端直接运行webpack,而不需要输入任何的参数,因为在webpack.config文件中已经定义了。运行结果如下图所示:

添加快捷方式

在命令行中输入一个长的命令,比如node_modules/.bin/webpack/是很烦人而且容易出错的。幸运的是,可以通过在package.json文件中进行简单的配置后,就可以使用简单的npm start命令来执行上面的任务了。

{  "name": "sapmle-project",  "version": "1.0.0",  "main": "main.js",  "scripts": {    "start": "webpack" //修改这里  },  "license": "ISC",  "devDependencies": {    "webpack": "^3.8.1"  }}

注:package.json中的script会安装一定顺序寻找命令对应位置,本地的node_modules/.bin路径就在这个寻找清单中,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。

npm的start命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name},如npm run build,现在我们在命令行中输入npm start后,输出结果如下:

生成Source Maps

将所有的JavaScript模块打包成一个js文件在浏览器中使用有很多的优点,也有一个明显的缺点就是当发生错误时,无法通过打包后的文件找到对应的源文件发生错误的位置。source map提供了一种对应编译后的文件和源文件的对应方法,使得编译后的文件的可读性增强,同时更加易于在浏览器中进行调试。
在webpack的配置文件中配置source maps,需要配置devtool,它有以下四种不同的配置选项,各具优缺点,描述如下:

devtool选项 配置结果 source-map 在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度; cheap-module-source-map 在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便; eval-source-map 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的source map,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项; cheap-module-eval-source-map 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点;

正如上表所述,上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对打包后的文件的的执行有一定影响。

对小到中型的项目中,eval-source-map是一个很好的选项,再次强调你只应该开发阶段使用它,我们继续对上文新建的webpack.config.js,进行如下配置:

module.exports = {    devtool: 'eval-source-map', //修改这里    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    }}

cheap-module-eval-source-map 方法构建速度更快,但是不利于调试,推荐在大型项目考虑时间成本时使用。

Webpack搭建本地服务器

首先安装webpack-dev-server

npm install –save-dev webpack-dev-server

devserver可以在webpack.config.js中进行配置,它的配置项包括:

devserver的配置选项 功能描述 contentBase 默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public”目录) port 设置默认监听端口,如果省略,默认为8080 inline 设置为true,当源文件改变时会自动刷新页面 historyApiFallback 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html

把这些命令加到webpack的配置文件中,现在的配置文件webpack.config.js如下所示:

module.exports = {    devtool: 'eval-source-map',    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    }}

为了方便,在package.json中的script对象下添加如下命令,用以开启服务器:

{  "name": "sapmle-project",  "version": "1.0.0",  "main": "main.js",  "scripts": {    "start": "webpack",    "server": "webpack-dev-server --open" //填在这里  },  "license": "ISC",  "devDependencies": {    "webpack": "^3.8.1"  }}

在终端输入npm run server,可看到如下结果:

在浏览器中输入http://localhost:8080即可看到与之前相同的页面。

Loaders

loaders是webpack中最激动人心的功能之一。通过使用不同的loaders,webpack可以调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换lesss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。

Loaders需要单独安装并且需要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括以下几方面:


  • test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude: 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)
    为了距离说明,我们首先修改我们的示例文件(Greeter.js),将问候文本移动到一个单独的json文件中。首先我们来安装json loader模块:

npm install –save json-loader
然后修改webpack配置文件,将json loader加进去,修改后的文件如下:

module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    //添加在这里    module: {        rules: [{            test: /\.json$/,            use: "json-loader"        }]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    }}

在app文件夹中新建一个config.json文件,其内容如下:

{    "greetText": "Hi there and greeting from JSON!"}

修改后的Greeter.js:

var config = require("./config.json");module.exports = function() {    var greet = document.createElement('div');    greet.textContent = config.greetText;    return greet;}

由于webpack3.*/webpack2.*已经内置可处理JSON文件,这里我们可以无需再添加webpack1.*需要的json-loader

Babel

Babel是一个编译JavaScript的平台,它的强大之处表现在可以通过编译帮你达到以下目的:
- 使用下一代的JavaScript代码(ES6,ES7…),即使这些标准目前并未被当前的浏览器完全的支持;
- 使用基于JavaScript进行了拓展的语言,比如React的JSX;
Babel是一个独立的工具,但它也可以作为loader与Webpack配合使用。
安装和配置
Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-preset-es2015包和解析JSXbabel-preset-react包)。
首先来一次性安装这些包:

npm install –save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

与其他loaders一样,babel也需要在webpack配置文件的module下进行配置,配置方法如下:

module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                    option: {                        presets: ["es2015", "react"]                    }                }            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    }}

现在你的webpack的配置已经允许你使用ES6以及JSX的语法了。继续用上面的例子进行测试,不过这次我们会使用React,首先来安装 React 和 React-DOM:

npm install –save react react-dom

将Greeter按照ES6模块定义的方式进行修改,并返回一个React组件,修改后的文件:

import React, {Component} from "react";import config from "./config.json";class Greeter extends Component {    render() {        return (            <div>                {config.greetText}            </div>        )    }}export default Greeter;

同样的修改main.js:

import React from 'react';import { render } from  "react-dom";import Greeter from "./Greeter";render(<Greeter />, document.getElementById('root'));

Babel的配置
Babel可以完全在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,因此一些开发者支持把babel的配置选项放在一个单独的名为 “.babelrc” 的配置文件中。我们现在的babel的配置并不算复杂,不过之后我们会再加一些东西,因此现在我们就提取出相关部分,分两个配置文件进行配置(webpack会自动调用.babelrc里的babel配置选项),如下:

module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    }}
//.babelrc{    "presets": ["react", "es2015"]}

一切皆模块

Webpack有一个独特的特点是,它把所有的文件都都当做模块处理,JavaScript代码,CSS和fonts以及图片等等通过合适的loader都可以被处理。

CSS

Webpack提供两个工具处理样式表,css-loaderstyle-loader,二者处理的任务不同,css-loader使你能够使用类似@importurl(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
首先安装这两个loader:

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

配置:

module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader"                }]            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    }}

请注意这里对同一个文件引入多个loader的方法。

接下来,在app文件夹里创建一个名字为”main.css”的文件,对设置一些基础的元素样式:

//main.csshtml {    box-sizing: border-box;}*, *:before, *:after {    box-sizing: inherit;}body {    margin: 0;    padding: 0;    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;}h1,h2,h3,h4,h5,h6,p,ul {    margin: 0;    padding: 0;}

webpack只有单一的入口,其它的模块需要通过import, require, url等与入口文件建立其关联,为了让webpack能找到main.css文件,我们把它导入main.js中,如下:

import React from 'react';import { render } from  "react-dom";import Greeter from "./Greeter";import "./main.css"; //这里render(<Greeter />, document.getElementById('root'));

通常情况下,css会和js打包到同一个文件中,并不会打包为一个单独的css文件,不过通过合适的配置webpack也可以把css打包为单独的文件的。

上面的代码说明webpack是怎么把css当做模块看待的,咱们继续看一个更加真实的css模块实践。

CSS module

在过去的一些年里,JavaScript通过一些新的语言特性,更好的工具以及更好的实践方法(比如说模块化)发展得非常迅速。模块使得开发者把复杂的代码转化为小的,干净的,依赖声明明确的单元,配合优化工具,依赖管理和加载管理可以自动完成。

不过前端的另外一部分,CSS发展就相对慢一些,大多的样式表却依旧巨大且充满了全局类名,维护和修改都非常困难。

最近有一个叫做 CSS modules的技术就意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack从一开始就对CSS模块化提供了支持,在CSS loader中进行配置后,你所需要做的一切就是把modules传递到所需要的地方,然后就可以直接把CSS的类名传递到组件的代码中,且这样做只对当前组件有效,不必担心在不同的模块中使用相同的类名造成冲突。具体的代码如下:

module.exports = {    ...    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader",                    options: {                        modules: true                    }                }]            }        ]    },    devServer: {...}}

然后在app文件夹下创建一个Greeter.css文件:

.root {    background-color: #eee;    padding: 10px;    border: 3px solid #ccc;}

在Greeter.js中引入:

import React, {Component} from "react";import config from "./config.json";import styles from "./Greeter.css";class Greeter extends Component {    render() {        return (            <div className={styles.root}>                {config.greetText}            </div>        )    }}export default Greeter;

CSS预处理器

SassLess 之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables, nesting, mixins, inheritance等不存在于CSS中的特性来写CSSCSS预处理器可以将这些特殊类型的语句转化为浏览器可识别的CSS语句,

以下是常用的CSS预处理loaders:
Less Loader
Sass Loader
Stylus Loader

插件[Plugins]

插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。

Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Sass,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程起作用。

Webpack有很多内置插件,同时也有很多第三方插件,可以让我们完成更加丰富的功能。

使用插件的方法

要使用某个插件,我们需要通过npm安装它,然后要做的就是在webpack配置中的plugins关键字部分添加该插件的一个实例(plugins是一个数组)。继续上面的例子,添加一个给打包后代码添加版权声明的插件:

const webpack = require("webpack");  //引入webpackmodule.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/public",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader",                    options: {                        modules: true                    }                }]            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true    },    plugins: [        new webpack.BannerPlugin("版权所有,翻版必究")    ]}

通过这个插件,打包后的JS文件显示如下:

下面是几个常用的插件:

HTMLWebpackPlugin

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

npm install –save-dev html-webpack-plugin

接下来需要对项目中原有的文件进行如下修改:

  1. 移除public文件夹 利用此插件,会自动生成index.html文件,此外CSS已经通过前面的操作打包到JS中了,这整个文件夹已经没有必要了。
  2. 创建一个html模板文件 在app文件夹下,创建一个index.tmpl.html文件模板,这个模板包含title等必须元素,在编译过程中,插件会依据此模板生成最终的html页面,会自动添加所依赖的 css, js,favicon等文件。

    index.tmpl.html中的模板源代码如下:

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Webpack Sample Project</title></head><body>    <div id="root"></div></body></html>
  3. 更新webpack配置文件。

    const webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {devtool: "eval-source-map",entry: __dirname + "/app/main.js",output: {    path: __dirname + "/build",  //这里    filename: "bundle.js"},module: {    rules: [        {            test: /\.js$/,            exclude: /node_modules/,            use: {                loader: "babel-loader",            }        },        {            test: /\.css$/,            use: [{                loader: "style-loader"            },            {                loader: "css-loader",                options: {                    modules: true                }            }]        }    ]},devServer: {    contentBase: "./public",    historyApiFallback: true,    inline: true},plugins: [    new webpack.BannerPlugin("版权所有,翻版必究"),    new HtmlWebpackPlugin({        template: __dirname + "/app/index.tmpl.html" //这里    })]}

    再次运行npm run start,会自动生成build文件夹,并在该文件夹下生成bundle.jsindex.html文件。

Hot Module Replacement

Hot Module Replacement(HMR)也是webpack里很有用的一个插件,它允许你在修改组件代码后,自动刷新实时预览修改后的效果。

在webpack中实现HMR也很简单,只需要做两项配置

  1. 在webpack配置文件中添加HMR插件;
  2. 在Webpack Dev Server中添加“hot”参数;

不过配置完这些后,JS模块其实还是不能自动热加载的,还需要在你的JS模块中执行一个Webpack提供的API才能实现热加载,虽然这个API不难使用,但是如果是React模块,使用我们已经熟悉的Babel可以更方便的实现功能热加载。

整理下我们的思路,具体实现方法如下

  • Babel和webpack是独立的工具
  • 二者可以一起工作
  • 二者都可以通过插件拓展功能
  • HMR是一个webpack插件,它让你能浏览器中实时观察模块修改后的效果,但是如果你想让它工作,需要对模块进行额外的配额;
  • Babel有一个叫做react-transform-hrm的插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作;

还是继续上例来实际看看如何配置:

const webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/build",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader",                    options: {                        modules: true                    }                }]            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true,        hot: true //hot参数    },    plugins: [        new webpack.BannerPlugin("版权所有,翻版必究"),        new HtmlWebpackPlugin({            template: __dirname + "/app/index.tmpl.html"        }),        new webpack.HotModuleReplacementPlugin() //热加载插件    ]}

接下来安装Babel插件react-transform-hmr

npm install –save-dev babel-plugin-react-transform react-transform-hmr

然后编辑.bablerc配置文件来安装插件:

{    "presets": ["react", "es2015"],    "env": {        "development": {            "plugins": [["react-transform", {                "transforms": [{                    "transform": "react-transform-hmr",                    "imports": ["react"],                    "locals": ["module"]                }]            }]]        }    }}

启动npm run server,任意修改Greeter文件中的内容,会发现浏览器中显示的内容会实时更新。

产品阶段的构建

目前为止,我们已经使用webpack构建了一个完整的开发环境。但是在产品阶段,可能还需要对打包的文件进行额外的处理,比如说优化,压缩,缓存以及分离CSS和JS。

对于复杂的项目来说,需要复杂的配置,这时候分解配置文件为多个小的文件可以使得事情井井有条,以上面的例子来说,我们创建一个webpack.production.config.js的文件,在里面加上基本的配置,它和原始的webpack.config.js很像,如下:

// webpack.production.config.jsconst webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/build",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader",                    options: {                        modules: true                    }                }]            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true,        hot: true    },    plugins: [        new webpack.BannerPlugin("版权所有,翻版必究"),        new HtmlWebpackPlugin({            template: __dirname + "/app/index.tmpl.html"        }),        new webpack.HotModuleReplacementPlugin()    ]}
//package.json{  "name": "sapmle-project",  "version": "1.0.0",  "main": "main.js",  "scripts": {    "start": "webpack",    "server": "webpack-dev-server --open",    "build": "set NODE_ENV=production && webpack --config ./webpack.production.config.js --progress" //修改这里  },  "license": "ISC",  "devDependencies": {    "babel-core": "^6.26.0",    "babel-loader": "^7.1.2",    "babel-plugin-react-transform": "^3.0.0",    "babel-preset-es2015": "^6.24.1",    "babel-preset-react": "^6.24.1",    "css-loader": "^0.28.7",    "html-webpack-plugin": "^2.30.1",    "react-transform-hmr": "^1.0.4",    "style-loader": "^0.19.0",    "webpack": "^3.8.1",    "webpack-dev-server": "^2.9.3"  },  "dependencies": {    "json-loader": "^0.5.7",    "react": "^16.0.0",    "react-dom": "^16.0.0"  }}

此时运行npm run build就会按照webpack.production.config.js文件中的配置来运行webpack打包文件。

优化插件

webpack提供了一些在发布阶段非常有用的优化插件,它们大多来自于webpack社区,可以通过npm安装,通过以下插件可以完成产品发布阶段所需的功能


  • OccurenceOrderPlugin :为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
  • UglifyJsPlugin:压缩JS代码;
  • ExtractTextPlugin:分离CSS和JS文件
    我们继续用例子来看看如何添加它们,OccurenceOrderUglifyJS plugins 都是内置插件,你需要做的只是安装其它非内置插件:

npm install –save-dev extract-text-webpack-plugin
在配置文件的plugins后引用它们:

const webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");const ExtractTextPlugin = require("extract-text-webpack-plugin");//引入插件module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/build",        filename: "bundle.js"    },    module: {        rules: [            {                test: /\.js$/,                exclude: /node_modules/,                use: {                    loader: "babel-loader",                }            },            {                test: /\.css$/,                use: [{                    loader: "style-loader"                },                {                    loader: "css-loader",                    options: {                        modules: true                    }                }]            }        ]    },    devServer: {        contentBase: "./public",        historyApiFallback: true,        inline: true,        hot: true    },    plugins: [        new webpack.BannerPlugin("版权所有,翻版必究"),        new HtmlWebpackPlugin({            template: __dirname + "/app/index.tmpl.html"        }),        new webpack.HotModuleReplacementPlugin(),        new webpack.optimize.OccurrenceOrderPlugin(), // 添加插件        new webpack.optimize.UglifyJsPlugin(), // 添加插件        new ExtractTextPlugin("style.css") // 添加插件    ]}

此时运行npm run build之后的JS文件就是进行压缩后的了:

缓存

缓存无处不在,使用缓存的最好方法是保证你的文件名和文件内容是匹配的(内容改变,名称相应改变)

webpack可以把一个哈希值添加到打包的文件名中,使用方法如下,添加特殊的字符串混合体([name], [id] and [hash])到输出文件名前:

const webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");const ExtractTextPlugin = require("extract-text-webpack-plugin");module.exports = {    devtool: "eval-source-map",    entry: __dirname + "/app/main.js",    output: {        path: __dirname + "/build",        filename: "bundle-[hash].js" //这里    },    ...

此时打包后的js文件:

总结

到这里终于要结束了。最近正在学习react,在看pro-react这本书的时候,有一个附录文件是专门讲webpack配置的,于是乎就从网上下了下来准备看(全英文的),同时在网上搜webpack学习资料的时候,看到了这篇博客(入门Webpack,看这篇就够了),发现刚好基本是翻译的前面那篇文章,于是乎就懒得看英文了。。。参照这篇博客从头到尾自己操作了一遍,本文中的webpack用到的是最新版的3.8.1,对于原博客中出现的个别问题进行了修改。整个操作下来,感觉整个人都通透了。为了防止以后忘记,参(co)考(py)原来的博客形成了我的这篇总结。在此感谢原作者。