m

全干工程师

webpack深入浅出使用教程

Webpack是一个模块打包器。其主要目的是将JavaScript文件捆绑在浏览器中使用,但它也能够转换,捆绑或打包任何资源或资产,使用依赖关系的模块并生成代表这些模块的静态形式(.js, .css, .png),Webpack是运行在Node.js环境中,它是模块化解决方案的一种。

什么是模块化

比如一个网站它有三个页面A、B、C。页面对应的js: A => {a.js, b.js}, B => {a.js, c.js, d.js}, C => {a.js, e.js, c.js}。
他们都有引入了a.js, 可以独立生成a.vendor.js。 然而B,C都引入a.js, c.js, 可以独立成ac.vednor.js

为什么使用Webpack

最大的好处就是配置完一键打包生成相应模块,通过插件还可以处理压缩,版本号,sourceMap,通过loader自动编译转换.less、.sass、.vue、.react等文件。无论对单入口还是多入口支持就非常到位,像其它的类似工具(browserify)对多入口没有Webpack强大。

Install

在使用Webpack之前需要安装Node.js, 下载地址

NPM

使用npm进行安装,安装node.js会自动安装npm

[root@BF-meshell webpack]# npm install --save-dev webpack

YARN

通过yarn安装

[root@BF-meshell webpack]# npm install yarn -g  //先安装yarn 
[root@BF-meshell webpack]# yarn add webpack --dev

webpack.config.js

webpack.config.jsWebpack配置文件(官方文档), 在配置之前我先生成package.json文件

//npm init 初始化项目的package.json文件
[root@BF-meshell webpack]# npm init

package.json

{
  "name": "webpack-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "meShell",
  "license": "MIT",
  "dependencies": {

  },
  "devDependencies": {

  }
}

我们需要修改就是devDependenciesdependencies属性(项目的依赖库). 通过npmjs找到你需要的包名.

//格式以包名为键,版本号为值。
"devDependencies": {
    "jquery": "^3.2.1",
    "superagent": "^3.8.1"
}

在配置完devDependenciesdependencies就可以执行安装依赖.

[root@BF-meshell webpack]# npm install

模块文件(入口文件)

新建两个入口文件index.jscontent.js两个文件都包含各自需要的类库以及应用代码,分别代表首页和内容的js文件. 主要功能就是显示当前页面的名称,取得远程的JSON数据显示出来。他们公用了两个类库jQuery4和superagent。有了入口文件就开始配置webpack.config.js

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
    entry: {
        index: "./index",
        content: "./content",
    },
    output: {
        path:  path.resolve(__dirname, 'dist'),
            filename: "[name].js"
    }
};

这是webpack的基本配置。在目录执行webpack命令就会生成目录dist同时在目录下生成index.jscontent.js

[root@BF-meshell webpack]# webpack 
Hash: 052f1069368009e4662d
Version: webpack 3.8.1
Time: 2099ms
       Asset       Size  Chunks                    Chunk Names
   content.js     314 kB       0  [emitted]        content
    index.js      314 kB       0  [emitted]        index

entry和output

entryoutput是配置文件里必须填写的属性.entry项目入口点可以是字符串,数组,对象形式来表达.
比如是单页面应用只有入口文件就可以这样的配置entry:"./app"; output作为入口点的输出形式如文件目录,文件名。

上面的配置是没有分离库和应用代码,而是将所有库都打包进index.jscontent.js,我们使用webpack自带的CommonsChunkPlugin插件来分离公共库和应用代码.

CommonsChunkPlugin

该插件功能是从多个入口文件中分离出公共库文件为一个独立的块文件。以index.jscontent.js为例,两个都加载了jquerysuperagent库只需配置如下代码到配置文件(plugins属性)中就会分离出一个common.js文件出来。

new webpack.optimize.CommonsChunkPlugin({
    names: ["common"],
})

这样就会把jquerysuperagent库合并到common.js中给页面加载如:

<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="index.js"></script>
<!-- 或者  -->
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="content.js"></script>

也可以通过chunks来指定入口文件分离.

new webpack.optimize.CommonsChunkPlugin({
    names: ["common"],
    chunks: ["index", "content"]
})

可以查看https://github.com/webpack/webpack/tree/master/examples/multiple-commons-chunks这个事例。上面我们完成了代码分离,我们需要两个html页面分测试最终效果这里用到HtmlWebpackPlugin.

new htmlWebpackPlugin({
    filename: "index.html",
}),
new htmlWebpackPlugin({
    filename: "content.html",
}),

将插件代码加入到配置中.

const path = require("path");
const webpack = require("webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
    entry: {
        index: "./index",
        content: "./content",
    },
    output: {
        path:  path.resolve(__dirname, 'dist'),
            filename: "[name].js"
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            names: ["common", "manifest"],
        }),
        new htmlWebpackPlugin({
            filename: "index.html",
        }),
        new htmlWebpackPlugin({
            filename: "content.html",
        })
    ]
};

执行webpack命令,生成以下目录文件。

webpack-path

index.html中的content.js引入删除和content.htmlindex.js删除,并在浏览器中查看两个页面的效果。

i-am-index
i-am-content

可以配置HtmlWebpackPlugin的chunks属性来解决引入多余的js文件.

new htmlWebpackPlugin({
    filename: "index.html",
    //页面将只会引入common.js、index.js
    chunks: ["common","index"],
})

Loader

前面讲完了代码的分离,现在学习loader的使用,webpack默认只会处理.js文件,如果需要将less,vue,sass等文件处理成可使用状态就要使用loaderwebpack将所有的静态资源文件都当成模块,然后通过loader来转换,它需要额外安装的,常用的loader列表.

Name Loader
css css-loader
less less-loader
sass sass-loader
style style-loader
url url-loader
file file-loader
json json-loader
babel babel-loader
html html-loader
vue vue-loader

https://webpack.js.org/loaders/

[root@BF-meshell webpack]# npm install css-loader less-loader sass-loader style-loader url-loader file-loader babel-loader --save-dev 

安装完成之后,在webpack配置中添加rules规则.

// webpack.config.js
module.exports = {
  module: {
        rules: [{
            test: /\.less$/, //区配文件是以.less结尾就style-loader, css-loader, less-loader来转换
            use: [{
                loader: "style-loader"
            }, {
                loader: "css-loader"
            }, {
                loader: "less-loader", options: {
                    strictMath: true,
                    noIeCompat: true
                }
            }]
        }]
    }
};

编写一个less测试文件内容就是官网的默认事例。

@baseColor: #f938ab;
@whiteColor: #FFFFFF;

body {
    background-color: saturate(@baseColor, 5%)}
h1 {
    color: @whiteColor;
    border-width: 1px;
    border-style: solid;
    border-color: @whiteColor;
}

修改index.js

require("./body.less");

Note:
直接使用webpack命令并不会直接产生body.css文件,我们将要使用extract-text-webpack-plugin插件将编译的css内容提取到文件中.

extract-text-webpack-plugin

修改配置文件,将extract-text-webpack-plugin添加进去。

...
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const extractLess = new ExtractTextPlugin({
    filename: "[name].css",
    disable: process.env.NODE_ENV === "development"
});
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.less$/, //区配文件是以.less结尾就style-loader, css-loader, less-loader来转换
                use:extractLess.extract({
                    use: [{
                        loader: "css-loader"
                    }, {
                        loader: "less-loader"
                    }],
                    // use style-loader in development
                    fallback: "style-loader"
                })
            }
        ]
    },
    resolve: {

    },
    plugins: [
        ...
        extractLess
    ]
};

重新编译就会生成一个index.css文件,也会直接引入到index.html中。

i-am-loader-css

通过上面的几个事例了解webpack基础使用,代码分离,loader使用.还可以使用插件对生成后的文件进行压缩、sourceMap文件、版本号、这些官网就有详细的讲解,本教程中就不再讲解.

事例代码https://github.com/TianLiangZhou/loocode-example/tree/master/webpack

推荐阅读

  1. 中文文档
  2. https://github.com/webpack/webpack/tree/master/examples

留言