webpack

作者: 刘昊2018 | 来源:发表于2018-01-16 17:32 被阅读22次

    官网
    中文文档
    中文文档
    webpack是目前前端工程化实践中最常用的打包工具,学习webpack,有利于我们掌握前端模块化编程,也是我们在学习React,Vue等框架时做为重要支撑。

    以下是官方和中文文档对webpack的概括

    At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into one or more bundles.

    本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

    起步

    安装

    创建目录,初始化npm。

    mkdir webpack-demo && cd webpack-demo
    cnpm init
    cnpm install webpack --save-dev
    

    说明:

    • cnpm是淘宝npm镜像,使用方法和npm一样。可以帮助我们提升包的下载速度。
    • cnpm install {packeg_name} --save-dev,package_name为要下载的包名称,--save-dev,表示将package-name添加到package.jsondevDependencies中。

    创建两个文件测试,index.htmlindex.js

    index.html

    <html>
      <head>
        <title>Getting Started</title>
      </head>
      <body>
        <script src="./dist/bundle.js"></script>
      </body>
    </html>
    

    其中,bundle.js是我们等会要生成的文件,先不用了解

    index.js

    function component() {
      var element = document.createElement('div');
    
      element.innerHTML = 'hello webpack'
    
      return element;
    }
    
    document.body.appendChild(component());
    

    此时的目录结构为:

    webpack-demo
      node_modules
      src
         index.js
      index.html
      package.json
    

    将项目搭建成上述结构,我们就能学习第一个命令webpack。我们的目标就是以index.js为入口,生成一个bundle.js文件,供index.html使用。

    webpack src/index.js dist/bundle.js
    Hash: 629328b9dd2012d414f7
    Version: webpack 3.10.0
    Time: 59ms
        Asset     Size  Chunks             Chunk Names
    bundle.js  2.64 kB       0  [emitted]  main
       [0] ./src/index.js 170 bytes {0} [built]
    

    如果出现上诉回应,就说说明执行成功。此时我们的项目结构是这样的:

    webpack-demo
      dist
         bundle.js
      node_modules
      src
         index.js
      index.html
      package.json
    

    可以看到dist/bundle.js就是webpack替我们生成的。

    在浏览器中打开index.html,可以看到hello webpack

    我们来看bundle.js究竟是个什么东西。

    cat dist/bundle.js
    //// 一堆被注释掉的代码
    function component() {
      var element = document.createElement('div');
    
      element.innerHTML = 'hello webpack'
    
      return element;
    }
    
    document.body.appendChild(component());
    // 这段代码是我们是从我们的index.js copy的。
    

    可以看到,对于我们自己写的函数,webpack会原封不动的copy过来。

    配置文件

    我们之前使用的webpack src/index.js dist/bundle.js其实可以使用一个配置文件来表述,比在终端中敲命令更加方便。

    创建文件 webpack.config.js
    此时:

      node_modules
      src
         index.js
      index.html
      package.json
      webpack.config.js
    
    const path = require('path');
    
    module.exports = {
      entry: './src/index.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      }
    };
    

    说明:

    • 其中,require是node.js内置函数表示引入模块,path是node.js内置模块。
    • entry是入口文件,就是我们的index.js
    • outpath表示输出目录及文件名。

    为了便于观察,我们删掉之前生成的dist目录及其文件

    我们执行命令:

    webpack --config webpack.config.js
    
    Hash: 629328b9dd2012d414f7
    Version: webpack 3.10.0
    Time: 59ms
        Asset     Size  Chunks             Chunk Names
    bundle.js  2.64 kB       0  [emitted]  main
       [0] ./src/index.js 170 bytes {0} [built]
    

    此时目录结构:

    webpack-demo
      dist
         bundle.js
      node_modules
      src
         index.js
      index.html
      package.json
    

    在浏览器中查看index.html,依然可以看到hello webpack

    需要注意的是配置文件命名不一定是webpack.config.js,可以自由命名,如果为webpack.config.js,在使用命令时,可以省略--config

    如果觉得输入webpack比较麻烦或陌生,可以这样来使用:
    package.json中加入如下代码:

    {
      "scripts":{
          "build":"webpack"
       }
    }
    

    以后我们在打包时,可以直接使用:

    cnpm run build
    
    以上是用webpack实现的最基本的构建过程。

    可以看到,我们的index.html是我们自己创建的,如果我们配置了多个入口文件或者修改了出口文件,自己再来修改index.html是很麻烦的,我们使用一个插件:

    cnpm install --save-dev html-webpack-plugin
    
    plugins:[
        new HtmlWebpackPlugin({
            title:'webpack-demo'
        })
      ]
    

    我们删除根目录下我们自己手写的index.html

    rm index.html
    cnpm run build
    dist 
      bundle.js
      index.html
      cat index.html
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <title>webpack-demo</title>
      </head>
      <body>
      <script type="text/javascript" src="bundle.js"></script></body>
    </html>
    

    我们发现,我们刚才安装的这个插件,已经帮我们书写好了index.html
    且引入了打包产生的js文件。这是非常方便的。

    管理资源

    除了javascript,还可以通过loader引入其他类型的文件,如css.

    加载CSS

    我们安装style-loader

    cnpm install --save-dev style-loader css-loader
    

    修改webpack.config.js:

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

    要严格按照如上写法,避免遇到问题。
    通过浏览器预览,我们发现hello webpack变成了红色。

    加载图片

    cnpm install --save-dev file-loader
    

    修改webpack.config.js:

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

    放入一张图片icon.pngsrc中。
    修改index.js:

    import MyImg from './icon.png';
    
    var img = new Image();
    img.src = MyImg;
    element.appendChild(img);
    

    我们通过build,发现此时我们的页面上显示了刚才添加的图片,这张图片被放在了dist中。

    管理输出

    因为代码改的比较频繁,我们的dist目录中的文件会越来越多,有的文件可能不再需要,所以,在每次构建前清理dist目录,是比较好的做法,因为只会生成用到的文件。

    cnpm install clean-webpack-plugin --save-dev
    

    修改webpack.config.js:

    const CleanWebpackPlugin = require('clean-webpack-plugin');
    plugins:[
      new CleanWebpackPlugin(['dist'])
    ]
    

    此时,执行build后,dist中的文件就不会再有不需要的文件了。

    开发

    现在我们有一个痛点,每次修改代码后,要手动重新webpack,才能查看改动后的情况,其实webpack给我们提供了多个方案,让我们在代码发生变化后自动编译代码:

    • webpack watch mode
    • webpack dev server
    • webpack dev middleware

    需要指出的是,这三种方案都比较常用,特别是在一些项目的脚手架中,都高频使用这些项目,比如vue-cli

    观察者模式

    修改package.json:

    {
      scripts:{
        "watch":"webpack --watch"
      }
    }
    

    此时,我们在终端中输入:

    `cnpm run watch`
    > webpack-demo@1.0.0 watch /Users/liuhao/Desktop/webpack-demo
    > webpack --watch
    
    clean-webpack-plugin: /Users/liuhao/Desktop/webpack-demo/dist has been removed.
    
    Webpack is watching the files…
    
    Hash: a6eb44b735ce8b5f1f68
    Version: webpack 3.10.0
    Time: 689ms
                                   Asset       Size  Chunks             Chunk Names
    22f56d054f6abc3b0683e95a6a3f5150.png    95.6 kB          [emitted]  
                               bundle.js    20.3 kB       0  [emitted]  main
                              index.html  183 bytes          [emitted]  
       [0] ./src/icon.png 82 bytes {0} [built]
       [1] ./src/index.js 333 bytes {0} [built]
       [2] ./src/style.css 1.04 kB {0} [built]
       [3] ./node_modules/.0.28.9@css-loader!./src/style.css 330 bytes {0} [built]
        + 4 hidden modules
    Child html-webpack-plugin for "index.html":
         1 asset
           [2] (webpack)/buildin/global.js 509 bytes {0} [built]
           [3] (webpack)/buildin/module.js 517 bytes {0} [built]
            + 2 hidden modules
    Hash: 0eb719c26b33a7a1afe0
    Version: webpack 3.10.0
    Time: 28ms
         Asset       Size  Chunks             Chunk Names
     bundle.js    20.3 kB       0  [emitted]  main
    index.html  183 bytes          [emitted]  
     + 1 hidden asset
       [1] ./src/index.js 337 bytes {0} [built]
        + 7 hidden modules
    Child html-webpack-plugin for "index.html":
         1 asset
           4 modules
    

    可以看到webpack watch模式开启后,webpack进程没有退出,一直在监听程序变动,我们手动改动某一个位置,webpack又会自动编译。这种方式的弊端就是,我们要观察页面,还是得手动刷新浏览器。

    webpack-dev-server

    如果说webpack --wacth只是webpack自带的一个简单工具,那么webpack-dev-server就非常有用了。它提供一个简单的web服务器,能够实时重新加载。webpack-dev-serverwebpack的另外一个项目,且出自于官方。

    cnpm install --save-dev webpack-dev-server
    

    修改webpack.config.js:

    devServer:{
      contentBase:'./dist'
    }
    

    修改package.json:

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

    此时,我们执行cnpm start,就会在8080端口起来一个服务。渲染出html页面。当我们修改代码后,server会自动编译,成功后会通知浏览器自动刷新,此时我们不要受到刷新浏览器,即可看到更新后的内容。

    webpack-dev-middleware

    webpack-dev-server一样,webpack-dev-middleware也是由webpack官方进行维护的,但是能进行更多的自定义设置。

    安装expresswebpack-dev-middleware
    其中,expressnode.js中优秀的web项目。

    cnpm install --save-dev express webpack-dev-middleware
    

    修改 webpack.config.js:

    output: {
      publicPath:'/'
    }
    

    创建server.js:

    const express = require('express');
    const webpack = require('webpack');
    const webpackDevMiddleware = require('webpack-dev-middleware');
    
    const app = express();
    const config = require('./webpack.config.js');
    const compiler = webpack(config);
    
    // Tell express to use the webpack-dev-middleware and use the webpack.config.js
    // configuration file as a base.
    app.use(webpackDevMiddleware(compiler, {
     publicPath: config.output.publicPath
    }));
    
    // Serve the files on port 3000.
    app.listen(3000, function () {
     console.log('Example app listening on port 3000!\n');
    });
    

    node.js server会启动在3000端口。
    我们添加一项script来快速启动server.js.

    {
      “scripts”:{
        "server":"node server.js"
      }
    }
    

    了解node.js的同学都知道node命令用来干啥,不在赘述。
    现在我们执行:

    cnpm run server
    

    此时也实现了自动编译,如果还希望同步到浏览器,还需要使用另外一个项目,webpack-hot-middleware

    以上,我们可以知道,webpack-dev-server是使用起来最方便的。
    这些内容,可以帮助我们在开发中,做到心中有数,后面我将结合es6+vue.js+webpack来演示单页应用的开发。

    相关文章

      网友评论

          本文标题:webpack

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