webpack打包

作者: puxiaotaoc | 来源:发表于2018-09-09 17:34 被阅读28次

    一、一个常见的webpack配置文件

    // 一个常见的webpack配置文件
    const webpack = require('webpack');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    module.exports = {
            entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
            output: {
                path: __dirname + "/build",
                filename: "bundle-[hash].js"
            },
            devtool: 'none',
            devServer: {
                contentBase: "./public", //本地服务器所加载的页面所在的目录
                historyApiFallback: true, //不跳转
                inline: true,
                hot: true
            },
            module: {
                rules: [{
                        test: /(\.jsx|\.js)$/,
                        use: {
                            loader: "babel-loader"
                        },
                        exclude: /node_modules/
                    }, {
                        test: /\.css$/,
                        use: ExtractTextPlugin.extract({
                            fallback: "style-loader",
                            use: [{
                                loader: "css-loader",
                                options: {
                                    modules: true,
                                    localIdentName: '[name]__[local]--[hash:base64:5]'
                                }
                            }, {
                                loader: "postcss-loader"
                            }],
                        })
                    }
                }
            ]
        },
        plugins: [
            new webpack.BannerPlugin('版权所有,翻版必究'),
            new HtmlWebpackPlugin({
                template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
            }),
            new webpack.optimize.OccurrenceOrderPlugin(),
            new webpack.optimize.UglifyJsPlugin(),
            new ExtractTextPlugin("style.css")
        ]
    };
    

    二、loader和plugin的区别

    loader

           loader相当于一个转换器,操作的是文件,可以将A文件进行编译形成B文件,例如将A.scss或A.less转变成B.css,是单纯的文件转换过程;

           Loader是webpack最重要的功能之一,Loader能够让webpack处理不同的文件,它可以将所有类型的文件转换成webpack能够处理的有效模块,然后利用webpack的打包能力,对他们进行处理,即将所有类型的文件转换成应用程序的依赖图可以直接引用的模块;

           1)loader可以将sass,less文件的写法转换成css,而不再使用其他转换工具;
           2)loader可以将ES6或ES7的代码转换成大多数浏览器兼容的JS代码;
           3)loader可以将React中的JSX转换成JavaScript代码;

           webpack中的Loader有两个目标:
           1)识别出应该被对应的loader进行转换的文件(使用test属性);
           2)转换这些文件,从而使其能够被添加到依赖图中(并最终添加到bundle中)(使用use属性);

           用法:Loader需要单独安装,需要什么Loader就使用npm安装即可,并对应webpack.config.js中的module属性:

    module:{
      rules: [{
           test:  // 用于匹配处理文件的扩展名的表达式,必须
           use:  // loader名称,就是要使用的模块名,必须
           include/exclude: // 手动添加必须处理的文件(夹)或屏蔽不需要处理的文件(夹),可选
           query:  // 为loader提供额外的设置选项,可选
      }]
    }
    
    // use有三种写法:
    // 方法一:直接用use:
    use:['style-loader','css-loader']
    
    // 方法二:将use换成loader:
    loader:['style-loader','css-loader']
    
    // 方法三:使用use + loader:
    module: {
            rules: [{
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
              },
              {
                test: /\.css$/,
                use: [{
                    loader: 'style-loader'
                  },
                  {
                    loader: 'css-loader',
                    options: {
                      modules: true
                    }
                  }]
               }]
             }
    
    plugin

           plugin相当于一个扩展器,它丰富了webpack本身,针对loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务;

           loader被用于转换某些类型的模块,而plugin则可以用于执行广泛的任务,插件的范围包括从打包优化和压缩,一直到重新定义环境中的变量,插件接口功能极其强大,可以用来处理各种各样的任务,plugin通过对节点的监听,从而找到合适的节点对文件做适当的处理;

    run:开始编译
    make:从entry开始递归分析依赖并对依赖进行build
    build-moodule:使用loader加载文件并build模块
    normal-module-loader:对loader加载的文件用acorn编译,生成抽象语法树AST
    program:开始对AST进行遍历,当遇到require时触发call
    require:事件
    seal:所有依赖build完成,开始对chunk进行优化(抽取公共模块、加hash等)
    optimize-chunk-assets:压缩代码
    emit:把各个chunk输出到结果文件
    

           想要使用一个插件,只需要require它,然后将它添加到plugins数组中,多数插件可以通过选项自定义,也可以在一个配置中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建它的一个实例;webpack插件是一个具有apply属性的JavaScript对象,apply属性会被webpack compiler调用,并且compiler对象可在整个编译周期访问;由于插件可以携带参数/选项,必须在webpack配置中,向plugins属性传入new实例;

    // webpack.config.js文件头部引入插件
    const uglify = require('uglifyjs-webpack-plugin');
    const htmlPlugin= require('html-webpack-plugin');
    
    // 插件配置
    plugins:[
       new uglify(),
       new htmlPlugin({
          minify:{
            removeAttributeQuotes: true
          },
          hash: true,
          template: './src/index.html'
        }),
    ],
    

           (1)JS 压缩:webpack中JS压缩使用的是 uglifyjs-webpack-plugin插件;

    const uglify = require('uglifyjs-webpack-plugin');
    plugins: [
       new uglify();
    ]
    

           注意:在开发环境中使用该插件会报错,因为在开发预览时需要明确报错行数和错误信息,所以不需要对JS压缩,而生产环境中才会对JS压缩,devServer用于开发环境,而压缩JS用于生产环境,在开发中做生产环境的事情,所以会报错;

           (2)打包HTML:要将 HTML 文件从 src 目录下打包到 dist 目录下,需要借助 html-webpack-plugin 插件,该插件需要安装;

    npm install html-webpack-plugin --save-dev
    
    // 配置:
    const htmlPlugin = require('html-webpack-plugin');
    plugins: [
       new htmlPlugin({
          minify: { // 对HTML文件进行压缩
            removeAttributeQuotes: true // 去除属性的双引号
          },
          hash: true, // 为了避免缓存js,加入 hash
          template: './src/index.html' // 要打包的HTML模板路径和文件名称
       })
    ]
    

    三、webpack-dev-server和http服务器如nginx有什么区别?

            webpack-dev-server 的原理:正向代理隐藏了真实的客户端,而反向代理隐藏了真实的服务器,webpack-dev-server 扮演了一个代理服务器的角色,由于服务器之间通信不会存在前端常见的同源策略,这样当请求 webpack-dev-server 时,它会从真实的服务器中请求数据,然后将数据发送给浏览器;
            webpack-dev-server 主要是启动了一个使用express的Http服务器,启动webpack-dev-server后,你在目标文件夹中是看不到编译后的文件的,实时编译后的文件都保存到了内存当中,因此使用webpack-dev-server进行开发的时候看不到编译后的文件;
            webpack-dev-server 使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效;

    var server = new WebpackDevServer(compiler, {
      contentBase: "/path/to/directory",
      //content-base 配置 
      hot: true,
      //开启 HMR,由 webpack-dev-server 发送 "webpackHotUpdate" 消息到客户端代码
      historyApiFallback: false,
      //单页应用 404 转向 index.html
      compress: true,
      //开启资源的 gzip 压缩
      proxy: {
        "**": "http://localhost:9090"
      },
      //代理配置,来源于 http-proxy-middleware
      setup: function(app) {
         //webpack-dev-server 本身是 Express 服务器可以添加自己的路由
        // app.get('/some/path', function(req, res) {
        //   res.json({ custom: 'response' });
        // });
      },
      //为 Express 服务器的 express.static 方法配置参数 http://expressjs.com/en/4x/api.html#express.static
      staticOptions: {
      },
      //在 inline 模式下用于控制在浏览器中打印的 log 级别,如`error`, `warning`, `info` or `none`.
      clientLogLevel: "info",
      //不在控制台打印任何 log
      quiet: false,
      //不输出启动 log
      noInfo: false,
      //webpack 不监听文件的变化,每次请求来的时候重新编译
      lazy: true,
      //文件名称
      filename: "bundle.js",
      //webpack 的 watch 配置,每隔多少秒检查文件的变化
      watchOptions: {
        aggregateTimeout: 300,
        poll: 1000
      },
      //output.path 的虚拟路径映射
      publicPath: "/assets/",
      //设置自定义 http 头
      headers: { "X-Custom-Header": "yes" },
      //打包状态信息输出配置
      stats: { colors: true },
      //配置 https 需要的证书等
      https: {
        cert: fs.readFileSync("path-to-cert-file.pem"),
        key: fs.readFileSync("path-to-key-file.pem"),
        cacert: fs.readFileSync("path-to-cacert-file.pem")
      }
    });
    server.listen(8080, "localhost", function() {});
    // server.close();
    

            bundle是由webpack打包出来的文件,chunk是指webpack在进行模块的依赖分析的时候,代码分割出来的代码块;module是开发中的单个模块;

            Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码,在webpack中Tree-shaking是通过uglifySPlugin来Tree-shaking JS,Css需要使用Purify-CSS;

    参考链接:
    入门webpack,看这篇就够了
    webpack3-loader和plugin的概念理解
    webpack-dev-server 核心概念

    相关文章

      网友评论

        本文标题:webpack打包

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