从零开始构建一个webpack项目

初始化package.json

npm init -y

安装webpack、babel以及基础loader

npm i webpack webpack-cli @babel/core @babel/preset-env @babel/plugin-transform-runtime babel-loader @babel/polyfill -D
npm i @babel/runtime @babel/runtime-corejs3 -D
# 支持可选链
npm i @babel/plugin-proposal-optional-chaining -D 

上面安装的依赖中:

  • @babel/core 负责将传入的代码转换成抽象语法树(AST),然后其他的插件便可以根据抽象语法树分析代码,对一些ES6+的代码进行兼容处理

  • @babel/preset-env 转化最新语法如箭头函数, class, 扩展运算符,想要转换最新的api还需引入babel-polyfill(eg: includes)

  • @babel/plugin-transform-runtime运行时引入 generators/async、babel-runtime/core-js(ES6->includes…)不会污染全局环境。

  • babel-loader

  • @babel/polyfill 一些新的api:Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。

    ES6 在Array对象上新增了Array.from方法。

  • @babel/runtime babel-polyfill解决了Babel不转换新API的问题,但是直接在代码中插入帮助函数,会导致污染了全局环境,并且不同的代码文件中包含重复的代码,导致编译后的代码体积变大。 (比如:上述的帮助函数_defineProperty有可能在很多的代码模块文件中都会被插入)

    Babel为了解决这个问题,提供了单独的包babel-runtime用以提供编译模块的工具函数, 启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数

  • babel/runtime-corejs3@babel/runtime-corejs 的一个版本,@babel/plugin-transform-runtime 运行时需要用到,代码有2和3两个版本,其中,2版本无法为实例方法提供polyfill,但3版本可以

创建webpack.config.js并添加最基础的对于js/jsx的loader配置

module.exports = {
  module:{
    rules: [
      {
        test: /\.jsx?$/,
        use:["babel-loader"],
        exclude:/node_modules/
      }
    ]
  }
};

添加一下babel的配置

可以直接在webpack.config.js中配置,也可以新建一个.babelrc文件进行配置

webpack.config.js中配置

module.exports = {
  entry:{
    common: [
      `babel-polyfill`
    ]
  },
  module:{
    rules: [
      {
        test: /\.jsx?$/,
        use:[
        	{
        		loader: "babel-loader",
        		options:{
        			presets:["@babel/preset-env"],
        			plugins:[
        				[
        					"@babel/plugin-transform-runtime",
        					{
        						"corejs": 3
        					}
        				]
        			]
        		}
        	}
        ],
        exclude:/node_modules/
      }
    ]
  }
};

.babelrc中配置

// .babelrc文件
{
  "presets":["@babel/preset-env"],
  "plugins":[
      [
        "@babel/plugin-transform-runtime",
        {
          "corejs": 3
        }
      ]
  ]
}

在webpack.config.js中设置mode

const envs = {
  "development": "development",
  "test": "development",
  "production": "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      }
    ]
  }
};

编译命令中指定编译类型

# 安装跨平台环境变量工具cross-env
npm install --save-dev cross-env

修改package.json中的编译命令

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "dev": "cross-env NODE_ENV=development npx webpack --watch",
        "test": "cross-env NODE_ENV=test",
        "prod": "cross-env NODE_ENV=production"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.8.6",
        "@babel/plugin-proposal-optional-chaining": "^7.8.3",
        "@babel/plugin-transform-runtime": "^7.8.3",
        "@babel/polyfill": "^7.8.3",
        "@babel/preset-env": "^7.8.6",
        "babel-loader": "^8.0.6",
        "webpack": "^4.42.0",
        "webpack-cli": "^3.3.11"
    }
}

在浏览器中访问

npm install html-webpack-plugin -D 

webpack.config.js中配置

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ]
};

安装开发服务器

npm install webpack-dev-server -D

修改package.json 中的开发命令,使用开发服务打开

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server",
        "test": "cross-env NODE_ENV=test",
        "prod": "cross-env NODE_ENV=production"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.8.6",
        "@babel/plugin-proposal-optional-chaining": "^7.8.3",
        "@babel/plugin-transform-runtime": "^7.8.3",
        "@babel/polyfill": "^7.8.3",
        "@babel/preset-env": "^7.8.6",
        "babel-loader": "^8.0.6",
        "html-webpack-plugin": "^3.2.0",
        "webpack": "^4.42.0",
        "webpack-cli": "^3.3.11",
        "webpack-dev-server": "^3.10.3"
    }
}

这样便可以通过http://localhost:8080访问到我们的网页了,你也可以在webpcak.config.js配置devServer开发服务器的选项:

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      '/api':'https://example.com'
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: "false", //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  }
};

配置开发这工具devtool

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      "/api": "https://example.com"
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: "false", //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  },
  devtool:
    envs[process.env.NODE_ENV] === "development"
      ? "cheap-module-eval-source-map"
      : "" //开发环境下使用
};

对样式文件进行解析

webpack没办法直接对css进行解析和处理,因此需要借助loader对目标样式进行解析,此处采用less方式

npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D
  • style-loader 动态创建 style 标签,将 css 插入到 head 中.

  • css-loader 负责处理 @import 等语句。

  • postcss-loaderautoprefixer,自动生成浏览器兼容性前缀 —— 2020了,应该没人去自己徒手去写浏览器前缀了吧

  • less-loader 负责处理编译 ‘.less’ 文件,将其转为 ‘css’

依赖安装完之后,需要在webpcak.config.js中的module.rules中添加对css或less文件的解析配置

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      },
      {
        test: /\.(le|c)ss$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              plugins: function() {
                return [
                  require("autoprefixer")({
                    overrideBrowserslist: [">0.25%", "not dead"]
                  })
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      "/api": "https://example.com"
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: false, //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  },
  devtool:
    envs[process.env.NODE_ENV] === "development"
      ? "cheap-module-eval-source-map"
      : "" //开发环境下使用
};

这样便可以在目标js中引入样式文件了

// index.js
import "./index.less";
import Person from "./Person";

let p = new Person("kiner", 18);
p.showInfo();

body {
    background: red;
}

对图片和字体文件的加载

npm install url-loader file-loader -D

安装完依赖之后,还需要配置webpack.config.js配置指定loader

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      // 解析js或jsx文件
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      },
      // 解析less或css样式文件
      {
        test: /\.(le|c)ss$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              plugins: function() {
                return [
                  require("autoprefixer")({
                    overrideBrowserslist: [">0.25%", "not dead"]
                  })
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      },
      // 解析图片、字体文件等资源
      {
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 10240, //10K
              esModule: false,
              name: '[name]_[hash:6].[ext]',
              outputPath: 'assets'// 将静态资源文件输出到assets目录
            }
          }
        ],
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      "/api": "https://example.com"
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: false, //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  },
  devtool:
    envs[process.env.NODE_ENV] === "development"
      ? "cheap-module-eval-source-map"
      : "" //开发环境下使用
};

处理在html中引用的图片

npm install html-withimg-loader -D

webpack.config.js中添加配置

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      // 解析js或jsx文件
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      },
      // 解析less或css样式文件
      {
        test: /\.(le|c)ss$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              plugins: function() {
                return [
                  require("autoprefixer")({
                    overrideBrowserslist: [">0.25%", "not dead"]
                  })
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      },
      // 解析图片、字体文件等资源
      {
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 10240, //10K
              esModule: false
            }
          }
        ],
        exclude: /node_modules/
      },
      // 解析html中的图片
      {
        test: /\.html$/,
        use: "html-withimg-loader"
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    })
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      "/api": "https://example.com"
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: false, //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  },
  devtool:
    envs[process.env.NODE_ENV] === "development"
      ? "cheap-module-eval-source-map"
      : "" //开发环境下使用
};

每次打包前清空dist目录

npm install clean-webpack-plugin -D

修改webpack.config.js

const HtmlWebpackPlugin = require("html-webpack-plugin");

const envs = {
  development: "development",
  test: "development",
  production: "production"
};
module.exports = {
  mode: envs[process.env.NODE_ENV], // 根据环境变量设置编译模式
  module: {
    rules: [
      // 解析js或jsx文件
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
              plugins: [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    corejs: 3
                  }
                ]
              ]
            }
          }
        ],
        exclude: /node_modules/ // 排除node_modules目录
      },
      // 解析less或css样式文件
      {
        test: /\.(le|c)ss$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              plugins: function() {
                return [
                  require("autoprefixer")({
                    overrideBrowserslist: [">0.25%", "not dead"]
                  })
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      },
      // 解析图片、字体文件等资源
      {
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 10240, //10K
              esModule: false
            }
          }
        ],
        exclude: /node_modules/
      },
      // 解析html中的图片
      {
        test: /\.html$/,
        use: "html-withimg-loader"
      }
    ]
  },
  plugins: [
    //数组 放着所有的webpack插件
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      filename: "index.html", //打包后的文件名
      minify: {
        removeAttributeQuotes: false, //是否删除属性的双引号
        collapseWhitespace: false //是否折叠空白
      },
      hash: true //是否加上hash,默认是 false
    }),
    //每次重新编译前清空输出目录,不需要传参数喔,它可以找到 outputPath
    new CleanWebpackPlugin()
  ],
  // 开发服务器
  devServer: {
    port: "3000", //默认是8080
    // 设置接口代理
    proxy: {
      "/api": "https://example.com"
    },
    quiet: false, //默认不启用
    inline: true, //默认开启 inline 模式,如果设置为false,开启 iframe 模式
    stats: "errors-only", //终端仅打印 error
    overlay: false, //默认不启用
    clientLogLevel: "silent", //日志等级
    compress: true //是否启用 gzip 压缩
  },
  devtool:
    envs[process.env.NODE_ENV] === "development"
      ? "cheap-module-eval-source-map"
      : "" //开发环境下使用
};

目前为止,一个基本的web项目的webpack就构建好了,当然,具体开发过程中还是有很多的情况需要特殊处理的,这时候,我们就根据不同的情况使用loader、plugin等方式加入特殊的插件和逻辑实现我们要的功能便可

发布了32 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u010651383/article/details/104630957