webpack3基础

安装及问题

  • 全局安装

    cnpm i webpack -g
    
  • 安装问题及解决

    // 问题
    We will use "npm" to install the CLI via "npm install -D webpack-cli".
    Do you want to install 'webpack-cli' (yes/no): no
    You need to install 'webpack-cli' to use webpack via CLI.
    
    // 解决
    // 参考 https://blog.csdn.net/qq_43238599/article/details/97026566
    
    这里提示安装 webpack-cli// 是因为到了webpack4, webpack 已经将 webpack 命令行相关的内容都迁移到 webpack-cli,所以除了 webpack 外,我们还需要安装 webpack-cli:
    
    npm install --save-dev webpack-cli -g
    
  • 检查是否安装成功

    webpack -v
    

使用

新建webpack.config.js

// 指定打包入口和出口‘
module.exports = {
    entry: './src/app.js',
    output: {
      filename: './dist/app.bundle.js'
    }
  };

在package.json中配置命令

{
  "name": "01_demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack -d --watch",
    "prod": "webpack -p"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "webpack": "^3.0.0"
  },
  "devDependencies": {
    "webpack": "^3.0.0"
  }
}

// -d 这个参数之前没介绍过,它的意思就是说包含 source maps,这个有什么用呢,就是让你在用浏览器调试的时候,可以很方便地定位到源文件

命令启动

npm run dev
npm run prod

puglins插件

html-Webpack-plugin 处理html

  • 插件地址https://github.com/jantimon/html-webpack-plugin

  • 安装

    cnpm install html-webpack-plugin@3.2.0 --save-dev
    
  • 使用

    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      entry: 'index.js',
      output: {
        path: __dirname + '/dist',
        filename: 'index_bundle.js'
      },
      plugins: [
        new HtmlWebpackPlugin()
      ]
    }
    
  • 细节配置

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
        entry: './src/app.js',
        output: {
          path: __dirname + '/dist',
          filename: 'app.bundle.js'
        },
        plugins: [
            new HtmlWebpackPlugin({
                title: 'Custom template',
                // Load a custom template (lodash by default)
                // 页面模板
                template: './src/index.html',
                // 压缩html
                minify: {
                // 去除文件空格
                    collapseWhitespace: true,
                  },
              })
        ]
      }
    
  • template对应的html模板

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1, user-scalable=no">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.js"></script>
        <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
        <body>
            hello
        </body>
    
    </html>
    

extract-text-webpack-plugin 把 CSS 分离成文件

  • 安装

    cnpm install --save-dev extract-text-webpack-plugin@2.1.2
    
  • 使用

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    const webpack = require('webpack');
    
    module.exports = {
      entry: "./src/app.js",
      output: {
        path: __dirname + "/dist",
        filename: "app.bundle.js",
      },
      // 插件
      plugins: [
        // 处理打包的html
        new HtmlWebpackPlugin({
          title: "Custom template",
          // Load a custom template (lodash by default)
          template: "./src/index.html",
          minify: {
            collapseWhitespace: true,
          },
          hash: true,
        }),
        // 分离打包后的css
        new ExtractTextPlugin("style.css"),
         // 添加 hmr plugin
        new webpack.HotModuleReplacementPlugin()
        
      ],
      module: {
        rules: [
          {
            test: /\.scss$/i,
            // 自右向左处理
            use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: ["css-loader", "sass-loader"],
            }),
          },
          
      },
      // devServer
      devServer: {
        //表示服务器将从哪个目录去查找内容文件(即页面文件,比如 HTML)
        // contentBase: path.join(__dirname, "dist"),
        port: 9000,
        open: true,
        // 将 webpack-dev-server 的重载代码添加到产出的 bundle 中
        // inline: true,
        // 开启 hmr 支持
        hot: true,
      },
    };
    
    

clean-webpack-plugin 清除

  • 安装

    cnpm i clean-webpack-plugin@0.1.17 --save-dev
    
  • 引入

    const CleanWebpackPlugin=require('clean-webpack-plugin');
    
  • 在plugins中使用

     // 清除之前的打包
        new CleanWebpackPlugin(['dist'])
    

uglifyjs-webpack-plugin 压缩js

我们需要在webpack.config.js中引入uglifyjs-webpack-glugin插件

const uglify = `require`('uglifyjs-webpack-plugin');

引入后在plugins配置里new一个 uglify对象就可以了,代码如下。

 plugins:[
        new uglify()
    ],

autoprefixer(自动添加前缀的插件)

自动处理css3属性前缀

PostCSS

PostCSS是一个CSS的处理平台,它可以帮助你的CSS实现更多的功能,但是今天我们就通过其中的一个加前缀的功能,初步了解一下PostCSS。

安装

需要安装两个包postcss-loader 和autoprefixer(自动添加前缀的插件)

cnpm i postcss-loader@3.0.0 autoprefixer@8.0.0 -D

postcss.config.js

postCSS推荐在项目根目录(和webpack.config.js同级),建立一个postcss.config.js文件。

postcss.config.js

module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

这就是对postCSS一个简单的配置,引入了autoprefixer插件。让postCSS拥有添加前缀的能力,它会根据 can i use 来增加相应的css3属性前缀。

编写loader

对postcss.config.js配置完成后,我们还需要编写我们的loader配置。

{
      test: /\.css$/,
      use: [
            {
              loader: "style-loader"
            }, {
              loader: "css-loader",
              options: {
                 modules: true
              }
            }, {
              loader: "postcss-loader"
            }
      ]
}

提取CSS

配置提取CSS的loader配置.

{
    test: /\.css$/,
    use: extractTextPlugin.extract({
        fallback: 'style-loader',
        use: [
            { loader: 'css-loader', options: { importLoaders: 1 } },
            'postcss-loader'
        ]
    })

}

总结:postcss还有很多功能,我希望小伙伴学会自学。这里给出postcss-loader的github地址:https://github.com/postcss/postcss-loader

PurifyCSS-webpack消除未使用的css

PurifyCSS

使用PurifyCSS可以大大减少CSS冗余,比如我们经常使用的BootStrap(140KB)就可以减少到只有35KB大小。这在实际开发当中是非常有用的。

安装PurifyCSS-webpack

从名字你就可以看出这是一个插件,而不是loader。所以这个需要安装还需要引入。 PurifyCSS-webpack要以来于purify-css这个包,所以这两个都需要安装。

npmn  i -D purifycss-webpack purify-css

这里的-D代表的是–save-dev ,只是一个简写。

引入glob

因为我们需要同步检查html模板,所以我们需要引入node的glob对象使用。在webpack.config.js文件头部引入glob。

const glob = `require`('glob');

引入purifycss-webpack

同样在webpack.config.js文件头部引入purifycss-webpack

const PurifyCSSPlugin = `require`("purifycss-webpack");

配置plugins

引入完成后我们需要在webpack.config.js里配置plugins。代码如下,重点看标黄部分。

plugins:[
    //new uglify() 
    new htmlPlugin({
        minify:{
            removeAttrubuteQuotes:true
        },
        hash:true,
        template:'./src/index.html'

    }),
    new extractTextPlugin("css/index.css"),
    new PurifyCSSPlugin({
        // Give paths to parse for rules. These should be absolute!
        paths: glob.sync(path.join(__dirname, 'src/*.html')),
        })

]

这里配置了一个paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了。

**注意:**使用这个插件必须配合extract-text-webpack-plugin这个插件,这个插件在前边的课程已经讲解过了。如果你还不会请自学一下。

配置好上边的代码,我们可以故意在css文件里写一些用不到的属性,然后用webpack打包,你会发现没用的CSS已经自动给你删除掉了。在工作中记得一定要配置这个plugins,因为这决定你代码的质量,非常有用。

loader加载器

处理样式

css-loaderstyle-loader 处理 CSS

  • 安装

    cnpm install --save-dev css-loader@3.3.0
    cnpm install --save-dev style-loader@1.0.0
    
  • 报错

    TypeError: this.getResolve is not a function
        at Object.loader (/Users/honor/Downloads/note/webapck学习/webpack3/01_demo/node_modules/_css-loader@5.2.0@css-loader/dist/index.js:62:27)
    
  • 解决参考

    • https://blog.csdn.net/qq_36069339/article/details/100544821
    • https://blog.csdn.net/qq_43377853/article/details/108485499
  • 在webpack.config.js中配置规则

    var HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: './src/app.js',
      output: {
        path: __dirname + '/dist',
        filename: 'app.bundle.js'
      },
      plugins: [new HtmlWebpackPlugin({
        template: './src/index.html',
        filename: 'index.html',
        minify: {
          collapseWhitespace: true,
        },
        hash: true,
      })],
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [ 'style-loader', 'css-loader' ]
          }
        ]
      }
    };
    

sass-loader 把 SASS 编译成 CSS

  • 安装

    cnpm install sass-loader@7.0.0 node-sass --save-dev
    
  • 报错

    // sass-loader版本过高运行错误
    TypeError: this.getOptions is not a function
    
    // 指定版本即可
    
  • 在webpack.config.js中配置相应的规则

    var HtmlWebpackPlugin = require('html-webpack-plugin');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    module.exports = {
      entry: './src/app.js',
      output: {
        path: __dirname + '/dist',
        filename: 'app.bundle.js'
      },
      plugins: [new HtmlWebpackPlugin({
          template: './src/index.html',
          filename: 'index.html',
          minify: {
            collapseWhitespace: true,
          },
          hash: true,
        }),
        new ExtractTextPlugin('style.css')
      ],
      module: {
        rules: [
          {
            test: /\.scss$/,
            use: ExtractTextPlugin.extract({
              fallback: 'style-loader',
              //resolve-url-loader may be chained before sass-loader if necessary
              use: ['css-loader', 'sass-loader']
            })
          }
        ]
      }
    };
    

postcss-loader 配合autoprefixer插件处理css前缀

处理图片

file-loader 解决引用路径的问题

拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件

  • 安装

    cnpm install --save-dev file-loader@4.0.0
    
  • 在rules中配置

    {
            test: /\.(png|jpe?g|gif|svg)$/i,
            use: [
              {
                loader: 'file-loader',
                options: {
                  // [name] 代表文件名,[ext] 代表文件扩展名,outputPath 是输出的路径
                  name: '[name].[ext]',
                  outputPath: 'img/',
                },
              },
            ],
          },
    

url-loader 将图片编码

如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy

配置url-loader

我们安装好后,就可以使用这个loader了,记得在loader使用时不需要用require引入,在plugins才需要使用require引入。

webpack.config.js文件

 //模块:例如解读CSS,图片如何转换,压缩
    module:{
        rules: [
            {
              test: /\.css$/,
              use: [ 'style-loader', 'css-loader' ]
            },{
               test:/\.(png|jpg|gif)/ ,
               use:[{
                   loader:'url-loader',
                   options:{
                       limit:500000
                   }
               }]
            }
          ]
    },
  • test:/.(png|jpg|gif)/是匹配图片文件后缀名称。
  • use:是指定使用的loader和loader的配置参数。
  • limit:是把小于500000B的文件打成Base64的格式,写入JS。

写好后就可以使用webpack进行打包了,这回你会发现打包很顺利的完成了。具体的Base64的格式,你可以查看视频中的样子。

为什么只使用了url-loader

有的小伙伴会发现我们并没有在webpack.config.js中使用file-loader,但是依然打包成功了。我们需要了解file-loader和url-loader的关系。url-loader和file-loader是什么关系呢?简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:

1.文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);

2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。

也就是说,其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上file-loader。

处理html

html-loader 发布HTML

  • 安装

    cnpm install --save-dev html-loader
    
  • 配置rules

    {
      test: /\.html$/,
      use: [ {
        loader: 'html-loader',
        options: {
          minimize: true,
          hash:true,
          template:'./src/index.html'
        }
      }],
    }
    
  • minify:是对html文件进行压缩,removeAttrubuteQuotes是却掉属性的双引号。

  • hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。

  • template:是要打包的html模版路径和文件名称。

image-webpack-loader 压缩图片

  • 安装

    cnpm install image-webpack-loader --save-dev
    
  • 在webpack.config.js中配置

    {
      test: /\.(gif|png|jpe?g|svg)$/i,
      use: [
        {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'images/'
          }
        },
        {
          loader: 'image-webpack-loader',
          options: {
            bypassOnDebug: true,
          }
        }
      ]
    },
    {
      test: /\.html$/,
      use: [ {
        loader: 'html-loader',
        options: {
          minimize: true
        }
      }],
    }
    

webpack-dev-derver本地开发服务

  • 文档

    • https://github.com/webpack/webpack-dev-server
    • https://webpack.js.org/configuration/dev-server/#devserver
  • 原理

    • webpack-dev-server是一个基于 Express 的本地开发服务器(看 Roadmap 下个版本内核会从 Express 切换到 Koa)。它使用 webpack-dev-middleware 中间件来为通过 Webpack 打包生成的资源文件提供 Web 服务。它还有一个通过 Socket IO 连接着 webpack-dev-server 服务器的小型运行时程序。webpack-dev-server 发送关于编译状态的消息到客户端,客户端根据消息作出响应。

    • Tips:简单来说 webpack-dev-server 就是一个 Express 的小型服务器,它是通过 Express 的中间件 webpack-dev-middleware和 Webpack 进行交互的。所以我们如果自己的项目本身就是个 Express 服务器,那么可以使用 webpack-dev-middleware 和 webpack-hot-middleware 两个中间件来实现 HMR 功能。关于 webpack-dev-middleware 和 webpack-hot-middleware 中间件来实现 webpack-dev-server 的内容
      
  • 安装

    cnpm install -g webpack-dev-server
    cnpm install --save-dev webpack-dev-server@
    
  • 在package.json中配置

    {
      "name": "01_demo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "dev": "webpack -d --watch",
        "prod": "webpack -p",
        "serve": "webpack-dev-server"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "webpack": "^3.0.0",
        "webpack-cli": "^2.0.13"
      },
      "devDependencies": {
        "css-loader": "^3.3.0",
        "extract-text-webpack-plugin": "^2.1.2",
        "html-webpack-plugin": "^3.2.0",
        "node-sass": "^5.0.0",
        "sass-loader": "^7.0.0",
        "style-loader": "^1.0.0",
        "webpack": "^3.0.0",
        "webpack-cli": "^2.0.13",
        "webpack-dev-server": "^2.9.7"
      }
    }
    
    
  • 在webpack.config.js中配置

     // devServer
      devServer: {
        //表示服务器将从哪个目录去查找内容文件(即页面文件,比如 HTML)
        // contentBase: path.join(__dirname, "dist"),
        port: 9000,
        open: true,
        // 将 webpack-dev-server 的重载代码添加到产出的 bundle 中
        // inline: true,
        // 开启 hmr 支持
        hot: true,
      },
    

命令行

webpack-dev-server 安装之后,会提供一个 bin 命令行,通过命令行可以启动对应的服务。

# 项目中安装 webpack-dev-server
npm i webpack-dev-server
# 使用 npx 启动
npx webpack-dev-server

执行webpack-dev-server命令之后,它会读取 Webpack 的配置文件(默认是 webpack.config.js)然后将文件打包到内存中(所以看不到dist文件夹的生产,Webpack 会打包到硬盘上),这时候打开 server 的默认地址:localhost:8080就可以看到文件目录或者页面(默认是显示 index.html,没有则显示目录)。

webpack-cli一样,webpack-dev-server也有一些选项可以添加:

# 修改端口号和 host
webpack-dev-server --port 3000 --host 127.0.0.1
# 启动inline 模式的自动刷新
webpack-dev-server --hot --inline
# 手动指定 webpack config 文件
webpack-dev-server --config webpack.xxx.js
# 指定 webpack 的 mode
webpack-dev-server --mode development
# watch 功能,文件发生变化则触发重新编译
webpack-dev-server --watch
# dev-server默认会将工作目录(当前目录)作为基本目录,可以手动修改它
webpack-dev-server --content-base ./build

上面只介绍了常用的并且比较重要的一些命令行选项,要查看全部,可以使用webpack-dev-server -h查看帮助。

我们还可以将webpack-dev-server放到package.jsonscripts里面,例如下面的例子,执行npm run dev实际就是执行的对应webpack-dev-server命令:

{
    "scripts": {
        "dev": "webpack-dev-server --mode development --config webpack.config.dev.js --hot --inline --port 3000"
    }
}

自动刷新

在开发中,我们希望边写代码,边看到代码的执行情况,webpack-dev-server 提供自动刷新页面的功能可以满足我们的需求。webpack-dev-server 支持两种模式的自动刷新页面。

  • iframe 模式:页面被放到一个 iframe 内,当发生变化时,会重新加载;
  • inline 模式:将 webpack-dev-server 的重载代码添加到产出的 bundle 中。

两种模式都支持模块热替换(Hot Module Replacement)。模块热替换的好处是只替换更新的部分,而不是整个页面都重新加载。

使用方式:webpack-dev-server --hot --inline是开启inline模式的自动刷新。

在开发中,我们希望边写代码,边看到代码的执行情况,webpack-dev-server 提供自动刷新页面的功能可以满足我们的需求。webpack-dev-server 支持两种模式的自动刷新页面。

  • iframe 模式:页面被放到一个 iframe 内,当发生变化时,会重新加载;
  • inline 模式:将 webpack-dev-server 的重载代码添加到产出的 bundle 中。

两种模式都支持模块热替换(Hot Module Replacement)。模块热替换的好处是只替换更新的部分,而不是整个页面都重新加载。

使用方式:webpack-dev-server --hot --inline是开启inline模式的自动刷新。

Hot Module Replacement

HMR 即模块热替换(Hot Module Replacement)的简称,它可以在应用运行的时候,不需要刷新页面,就可以直接替换、增删模块。

Webpack 可以通过配置 webpack.HotModuleReplacementPlugin 插件来开启全局的 HMR 能力,开启后 bundle 文件会变大一些,因为它加入了一个小型的 HMR 运行时(runtime),当你的应用在运行的时候,Webpack 监听到文件变更并重新打包模块时,HMR 会判断这些模块是否接受 update,若允许,则发信号通知应用进行热替换。

要开启 HMR 功能,需要三步:

  1. 设置

    devServer.hot=true
    
    devServer.inline=true
    

    (默认);

    • devServer.hot=true:会给 entry 添加webpack/hot/dev-serve或者webpack/hot/only-dev-servedevServer.hotOnly=true),这个是实现 HMR 的服务端代码;
    • devServer.inline=true:会给 entry 添加webpack-dev-server/client,这是通信客户端;
  2. webpack.config.js中添加 plugins:new webpack.HotModuleReplacementPlugin()

  3. 修改入口文件添加 HMR 支持代码:

// 在入口文件index.js最后添加如下代码
if (module.hot) {
    // 通知 webpack 该模块接受 hmr
    module.hot.accept(err => {
        if (err) {
            console.error('Cannot apply HMR update.', err);
        }
    });
}

最终修改后的webpack.config.js内容如下:

const path = require('path');
module.exports = {
    entry: './src/index.js',
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        port: 9000,
        // 开启 hmr 支持
        hot: true
    },
    plugins: [
        // 添加 hmr plugin
        new webpack.HotModuleReplacementPlugin()
    ]
};

经过上面配置之后,再次执行webpack-dev-server,打开http://localhost:9000,然后修改index.js内容,就能看到效果了

图片描述

Tips:使用 webpack-dev-server 的 CLI 功能只需要命令行中添加--hot,webpack-dev-server 会自动将webpack.HotModuleReplacementPlugin这个插件添加到 Webpack 的配置中去,所以开启 HotModuleReplacementPlugin 最简单的方式就是使用 inline 模式(命令行添加--inline

proxy

在实际开发中,本地开发服务器是不能直接请求线上数据接口的,这是因为浏览器的同源安全策略导致的跨域问题,我们可以使用devServer.proxy来解决本地开发跨域的问题。

下面的配置是将页面访问的/api所有请求都转发到了baidu.com上:

module.exports = {
    //...
    devServer: {
        proxy: {
            '/api': 'http://baidu.com'
        }
    }
};

devServer.proxy的值还支持高级属性,通过高级属性我们可以做更多的事情,如上面的需求变成,将/api/users转发到http://baidu.com/users,那么配置就需要改成:

module.exports = {
    //...
    devServer: {
        proxy: {
            '/api': {
                target: 'http://baidu.com',
                pathRewrite: {'^/api': ''}
            }
        }
    }
};

如果我们需要转发的网站是支持 https 的,那么需要增加secure=false,来防止转发失败:

module.exports = {
    //...
    devServer: {
        proxy: {
            '/api': {
                target: 'https://baidu.com',
                secure: false,
                pathRewrite: {'^/api': ''}
            }
        }
    }
};

又有新的需求了,这时候只能代理json接口的数据,对于html文件,还是使用打包后 dist 文件夹中文件,那么我们使用bypass来实现这个需求:

module.exports = {
    //...
    devServer: {
        proxy: {
            '/api': {
                target: 'http://baidu.com',
                bypass(req, res, proxyOptions) {
                    // 判断请求头中的 accept 值
                    if (req.headers.accept.indexOf('html') !== -1) {
                        console.log('Skipping proxy for browser request.');
                        // 返回的是 contentBase 的路径
                        return '/index.html';
                    }
                }
            }
        }
    }
};

或者,我们需要代理http://baidu.com下面的/api/auth两个地址,其他的地址都放行,这时候可以使用context

module.exports = {
    //...
    devServer: {
        proxy: [
            {
                context: ['/auth', '/api'],
                target: 'http://baidu.com'
            }
        ]
    }
};

自定义中间件

在 webpack-dev-server 中有两个时机可以插入自己实现的中间件,分别是在devServer.beforedevServer.after两个时机,即 webpack-dev-server 加载所有内部中间件之前和之后两个时机。

module.exports = {
    //...
    devServer: {
        before(app, server) {
            app.get('/some/path', (req, res) => {
                res.json({custom: 'response'});
            });
        }
    }
};

自定义中间件在开发中常常被用来当作 mock server 使用。

详情参见https://juejin.cn/post/6844903606420766734

Webpack Dev Server 常用配置

  • devServer.historyApiFallback:配置如果找不到页面就默认显示的页面;
  • devServer.compress:启用 gzip 压缩;
  • devServer.hotOnly:构建失败的时候是否不允许回退到使用刷新网页;
  • devServer.inline:模式切换,默认为内联模式,使用false切换到 iframe 模式;
  • devServer.open:启动后,是否自动使用浏览器打开首页;
  • devServer.openPage:启动后,自动使用浏览器打开设置的页面;
  • devServer.overlay:是否允许使用全屏覆盖的方式显示编译错误,默认不允许;
  • devServer.port:监听端口号,默认 8080;
  • devServer.host:指定 host,使用0.0.0.0可以让局域网内可访问;
  • devServer.contentBase:告诉服务器从哪里提供内容,只有在你想要提供静态文件时才需要;
  • devServer.publicPath:设置内存中的打包文件的虚拟路径映射,区别于output.publicPath
  • devServer.staticOptions:为 Expressjs 的 express.static配置参数,参考文档: http://expressjs.com/en/4x/api.html#express.static
  • devServer.clientLogLevel:在 inline 模式下用于控制在浏览器中打印的 log 级别,如error, warning, info or none
  • devServer.quiet:静默模式,设置为true则不在控制台输出 log;
  • devServer.noInfo:不输出启动 log;
  • devServer.lazy: 不监听文件变化,而是当请求来的时候再重新编译;
  • devServer.watchOptions:watch 相关配置,可以用于控制间隔多少秒检测文件的变化;
  • devServer.headers:自定义请求头,例如自定义 userAgent 等;
  • devServer.https:https 需要的证书签名等配置。

Webpack 中配置React和Vue开发环境

Webpack 中配置 React 的开发

首先是创建目录、初始化 package.json、安装 React、安装 Webpack 和安装 Babel。

# 新建目录,并且进入
mkdir react-webpack && cd $_
# 创建 package.json
npm init -y
# 安装 react react-dom依赖
cnpm i react react-dom -S
# 安装 webpack 和 webpack-cli 开发依赖
npm i webpack webpack-cli -D
# 安装 babel
cnpm i babel-loader@7.1.5 @babel/core @babel/preset-env -D

# 安装 babel preset-react
cnpm i @babel/preset-react -D

#创建 .babelrc 文件
{
  "presets": ["env", "react"]
}

因为 React 中提供了一种 JavaScript 的扩展语法,React 将它们命名为 jsx,所以在这里我们需要给 jsx 文件添加 Babel 的编译支持,现在我们新建一个 webpack.config.js 的配置文件,内容和注释如下:

使用babel-loader

  • 安装
cnpm install --save-dev babel-loader@7.1.5
  • 问题

    • Module build failed: Error: Plugin/Preset files are not allowed to export objects

    • 解决 https://blog.csdn.net/ljxzuishuai/article/details/103886908

    • Error:Node Sass version 5.0.0 is incompatible with ^4.0.0

    • 解决 https://blog.csdn.net/weixin_42390302/article/details/109443294

  • 在webpack.config.js中配置

     module: {
        rules: [
          {
            test: /\.scss$/i,
            // 自右向左处理
            use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: ["css-loader", "sass-loader"],
            }),
          },
          // 这两行是处理 react 相关的内容
          { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
          { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
        ],
      },
    

react 组件

接着我们来准备一些 react 的代码,要来测试一下。

src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hello World</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

复制代码

src/app.js

import css from './app.scss';

import React from 'react';
import ReactDOM from 'react-dom';
import Root from './Root';

ReactDOM.render(
  <Root></Root>,
  document.getElementById('root')
);

复制代码

src/Root.js

import React from 'react';

export default class Root extends React.Component {
  render() {
    return (
      <div style={{textAlign: 'center'}}>
        <h1>Hello World</h1>
      </div>);
  }
}

复制代码

效果如下:

img

参考链接:

配置多入口文件

  • 多个entry

     entry: {
        "app.bundle": './src/app.js',
        "contact":"./src/contact.js"
      },
    
  • 多个HtmlWebpackPlugin

    • chunks就是本文件,对应加载的文件
    • excludeChunks就是除开该文件
    plugins: [
        // 处理打包的html
        new HtmlWebpackPlugin({
          title: "Custom template",
          // Load a custom template (lodash by default)
          template: "./src/index.html",
          filename:"index.html",
          minify: {
            collapseWhitespace: true,
          },
          hash: true,
        }),
        new HtmlWebpackPlugin({
          title: "contact page",
          // Load a custom template (lodash by default)
          template: "./src/contact.html",
          filename:"contact.html",
          minify: {
            collapseWhitespace: true,
          },
          hash: true,
          chunks:['contact']
        }),
        // 分离打包后的css
        new ExtractTextPlugin("style.css"),
         // 添加 hmr plugin
        new webpack.HotModuleReplacementPlugin(),
        // 清除之前的打包
        new CleanWebpackPlugin(['dist'])
        
      ],
    

模板引擎

hogan.js

https://www.cnblogs.com/zhangruiqi/p/8547268.html

http://twitter.github.io/hogan.js/

jade

https://github.com/pugjs/pug

  • 安装

     cnpm install pug --save-dev
    

raw-loader将文件转化为字符串

https://github.com/webpack-contrib/raw-loader

  • 安装

    cnpm install raw-loader --save-dev
    

pug-html-loader

  • 安装

    cnpm install pug-html-loader@1.1.5 --save-dev
    

将index.html文件后缀改为index.pug,并在webpack.config.js中配置规则

{ test: /\.pug$/, loader: ['raw-loader', 'pug-html-loader'] }

区分生产环境和开发环境

  • 在package.json中定义环境变量NODE_ENV

    "scripts": {
      "dev": "webpack-dev-server",
      "prod": "NODE_ENV=production webpack -p"
    },
    
  • 在webpack.config.js中使用环境变量

    var isProd = process.env.NODE_ENV === 'production'; // true or false
    
  • 根据环境变量判断是开发环境,还是生产环境,从而决定是否分离css,做相应的extract-text-webpack-plugin插件处理

    ...
    
    var isProd = process.env.NODE_ENV === 'production'; // true or false
    var cssDev = ['style-loader', 'css-loader', 'sass-loader'];
    var cssProd = ExtractTextPlugin.extract({
      fallback: 'style-loader',
      //resolve-url-loader may be chained before sass-loader if necessary
      use: ['css-loader', 'sass-loader']
    })
    
    var cssConfig = isProd ? cssProd : cssDev;
    
    module.exports = {
      ...
      plugins: [
        ...
        new ExtractTextPlugin({
          filename: 'style.css',
          disable: !isProd
        }),
        ...
      ],
      module: {
        rules: [
          {
            test: /\.scss$/,
            use: cssConfig
          },
          ...
        ]
      }
    };
    
    

打包后调试

在使用webpack时只要通过简单的devtool配置,webapck就会自动给我们生产source maps 文件,map文件是一种对应编译文件和源文件的方法,让我们调试起来更简单。

四种选项

在配置devtool时,webpack给我们提供了四种选项。

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

四种打包模式,有上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对执行和调试有一定的影响。

个人意见是,如果大型项目可以使用source-map,如果是中小型项目使用eval-source-map就完全可以应对,需要强调说明的是,source map只适用于开发阶段,上线前记得修改这些调试设置。

简单的配置:

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

总结:调试在开发中也是必不可少的,但是一定要记得在上线前一定要修改webpack配置,在打出上线包。

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值