zoukankan      html  css  js  c++  java
  • webpack 4 :从0配置到项目搭建

    webpack4发布以来,我写项目都是用脚手架,即使再简单的项目,真的是really shame。。虽然道听途说了很多 webpack4 的特性,却没有尝试过,因为它给人的感觉就是,em...很难。但是今天我从最简单的部分开始,一点点搭建起一个项目。

    0配置,配置了什么

    让我们从0开始,新建一个项目,在终端执行以下语句:

    mkdir webpack-4-quickstart && cd webpack-4-quickstart
    npm init -y
    npm i webpack --save-dev
    npm i webpack-cli --save-dev
    

    修改代码 package.jsonscripts 部分:

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

    现在,我们的 package.json 是这样的:

    {
      "name": "webpack-4-quickstart",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
         "build": "webpack"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "webpack": "^4.14.0",
        "webpack-cli": "^3.0.8"
      }
    }
    

    此时,我们执行 npm run build, 会给出以下提示/错误:

    webpack4-error
    1. error: 没有入口文件
    2. warning: 建议设置 mode 选项

    entry & output

    为了解决第一个问题,我们尝试新建 src/index.js:

    console.log(`I'm a entry point`);
    

    此时再次执行 npm run build,成功打包出了 dist/main.js,因此我们可以得知:

    webpack4 more配置了 entry(入口) src/index.js 和output(出口) dist/main.js

    当然,如果你想覆盖这个配置(比如修改为 ./foo/src/js/index.js),可以在 package.json 修改:

    "scripts": {
      "dev": "webpack --mode development ./foo/src/js/index.js --output ./foo/main.js",
      "build": "webpack --mode production ./foo/src/js/index.js --output ./foo/main.js"
    }
    

    production & development

    webpack4 之前,我们写一个项目起码会设置两种类型文件:

    • 用于开发环境的webpack.dev.conf.js,定义 webpack 启动的服务器等
    • 用于生产环境的webpack.prod.conf.js,定义UglifyJSPlugin或其他配置等

    而 webpack4 的 mode 给出了两种配置:developmentproduction

    我们修改 package.jsonscripts 部分:

    "scripts": {
      "dev": "webpack --mode development",
      "build": "webpack --mode production"
    }
    

    我们分别执行 npm run devnpm run build

    webpack4-mode

    执行 npm run dev 打包的是未压缩的代码,而 npm run build 是压缩后的代码。

    • 生产模式下:启用了 代码压缩、作用域提升(scope hoisting)、 tree-shaking,使代码最精简
    • 开发模式下:相较于更小体积的代码,提供的是打包速度上的优化

    总结

    webpack 4 的零配置主要应用于:

    • entry 默认设置为 ./src/index.js
    • output 默认设置为 ./dist/main.js
    • productiondevelopment 两种模式

    项目搭建

    项目搭建,我们对webpack的诉求是:

    • js的处理:转换 ES6 代码,解决浏览器兼容问题
    • css的处理:编译css,自动添加前缀,抽取css到独立文件
    • html的处理:复制并压缩html文件
    • dist的清理:打包前清理源目录文件
    • assets的处理:静态资源处理
    • server的启用:development 模式下启动服务器并实时刷新

    转换 ES6 代码,解决浏览器兼容问题

    用 babel 转换 ES6 代码

    用 babel 转换 ES6 代码需要使用到 babel-loader ,我们需要安装一系列的依赖:

        npm i babel-core babel-loader babel-preset-env --save-dev
    

    然后在根目录新建一个babel配置文件 .babelrc

        {
            "presets": [
                "env"
            ]
        }
    

    那么如何将配置用于webpack打包中?

    • 新建一个 webpack 的配置文件
    • 在 npm scripts 中使用 --module-bind
    1. 使用 webpack 的配置文件的方法:

      新建 webpack.config.js

          module.exports = {
            module: {
              rules: [
                {
                  test: /.js$/,
                  exclude: /node_modules/,
                  use: {
                    loader: "babel-loader"
                  }
                }
              ]
            }
          }
      
    2. 在 npm scripts 中配置的方法:

        "scripts": {
          "dev": "webpack --mode development --module-bind js=babel-loader",
          "build": "webpack --mode production --module-bind js=babel-loader"
        }
    

    使用 babel-polyfill 解决兼容性问题

    然而浏览器依然不支持一些语法的使用,导致兼容性问题,我们用 babel-polyfill 解决:

        npm i babel-polyfill babel-plugin-transform-runtime  --save-dev
    

    .babelrc 添加配置:

    {
        "presets": [
            "env"
        ],
        "plugins": [
           "transform-runtime"
        ]
    }
    

    最后在 webpack.config.js 中将 babel-polyfill 加到你的 entry 数组中:

    const path = require('path');
    module.exports = {
        entry: [
            "babel-polyfill",
            path.join(__dirname, './src/index.js')
        ],
        // ...
    };
    

    编译css,自动添加前缀,抽取css到独立文件

    webpack 并不会主动将你的css代码提取到一个文件,过去我们使用 extract-text-webpack-plugin,在webpack4中我们使用mini-css-extract-plugin来解决这个问题。

    postcss-loader 用于添加浏览器前缀,相关配置我喜欢在根目录新建 postcss.config.js 配置

        npm i mini-css-extract-plugin css-loader --save-dev
        npm i style-loader postcss-loader  --save-dev
    
        // webpack.config.js
        const MiniCssExtractPlugin = require("mini-css-extract-plugin");
        module.exports = (env, argv) => {
          const devMode = argv.mode !== 'production'
          return {
            module: {
              rules: [
                // ...,
                {
                    test: /.css$/,
                    use: [
                        devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
                        'css-loader',
                        'postcss-loader'
                    ]
                },
                ]
              },
              plugins: [
                // ...,
                new MiniCssExtractPlugin({
                  filename: "[name].css",
                  chunkFilename: "[id].css"
                })
              ]
          }
        }
    
    // postcss.config.js
        module.exports = {
            plugins: {
                autoprefixer: {}
            }
        }
    

    复制并压缩html文件 html-webpack-plugin

        npm i html-webpack-plugin html-loader --save-dev
    
        // webpack.config.js
        const HtmlWebPackPlugin = require("html-webpack-plugin");
        module.exports = {
            module: {
                rules: [
                    // ...,
                    {
                        test: /.html$/,
                        use: [{
                            loader: "html-loader",
                            options: {
                                minimize: true
                            }
                        }]
                    }
                ]
            },
            plugins: [
                new HtmlWebPackPlugin({
                    template: "./src/index.html",
                    filename: "./index.html"
                })
            ]
        };
    

    打包前清理源目录文件 clean-webpack-plugin

    每次打包,都会生成项目的静态资源,随着某些文件的增删,我们的 dist 目录下可能产生一些不再使用的静态资源,webpack并不会自动判断哪些是需要的资源,为了不让这些旧文件也部署到生产环境上占用空间,所以在 webpack 打包前最好能清理 dist 目录。

        npm install clean-webpack-plugin --save-dev
    
      const CleanWebpackPlugin = require('clean-webpack-plugin');
      module.exports = {
        plugins: [
          new CleanWebpackPlugin(['dist']),
        ]
      };
    

    静态资源处理 file-loader

        npm install file-loader --save-dev
    
        // webpack.config.js
        module.exports = {
          module: {
            rules: [
              {
                test: /.(png|jpg|gif)$/,
                use: [
                  {
                    loader: 'file-loader',
                    options: {}
                  }
                ]
              }
            ]
          }
        }
    

    development 模式下启动服务器并实时刷新 webpack-dev-server

        npm i webpack-dev-server --save-dev
    

    package.json

        "scripts": {
          "start": "webpack-dev-server --mode development --open",
          "build": "webpack --mode production"
        }
    

    使用 webpack 4 建立 react 项目

    现在我们模仿 create-react-app 的结构,自己搭建一个 react 项目,并且用less预编译:

      ├── public
      │   └── index.html      # html 模板
      ├── src
      │   ├── assets          # 静态资源
      │   │   └── logo.png
      │   ├── components      # 组件
      │   │   └── App.js
      │   ├── index.js        # 入口文件
      │   └── styles
      │       └── index.less
      ├── .babelrc
      ├── package-lock.json
      ├── package.json
      ├── postcss.config.js
      └── webpack.config.js
    

    在以上的基础(项目搭建部分),再安装react相关模块及less模块:

        npm i react react-dom --save
        npm i babel-preset-react --save-dev
        npm i less less-loader --save-dev
    

    修改 .babelrc:

        {
          "presets": ["env", "react"]
        }
    

    修改 webpack.config.js

        // webpack.config.js
        const path = require('path');
        module.exports = (env, argv) => {
            const devMode = argv.mode !== 'production'
            return {
                entry: [
                    "babel-polyfill",
                    path.join(__dirname, './src/index.js')
                ],
                devServer: {
                    port: 3000, //端口号
                },
                module: {
                    rules: [
                        // ...
                        // 处理react
                        {
                            test: /.(js|jsx)$/,
                            exclude: /node_modules/,
                            use: {
                                loader: "babel-loader"
                            }
                        },
                        // 处理less
                        {
                            test: /.less$/,
                            use: [
                                devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
                                'css-loader',
                                'postcss-loader',
                                'less-loader',
                            ]
                        }
                    ]
                }
            }
        };
    

    基本上搭建完这个项目了,如果你想看完整代码

    使用 webpack 4 建立 vue 项目

    同样地,我们模仿 vue-cli 的结构,自己搭建一个 vue 项目,这次我们的css预编译语言用 scss

      ├── public
      │   └── index.html      # html 模板
      ├── src
      │   ├── assets          # 静态资源
      │   │   └── logo.png
      │   ├── components      # 组件
      │   │   └── App.vue
      │   ├── main.js        # 入口文件
      │   ├── main.js        # 入口文件
      │   └── styles
      │       └── index.scss
      ├── .babelrc
      ├── package-lock.json
      ├── package.json
      ├── postcss.config.js
      └── webpack.config.js
    

    在以上的基础(项目搭建部分),再安装vue相关模块及sass模块:

        npm i vue --save
        npm i vue-loader vue-template-compiler --save-dev
        npm i node-sass sass-loader --save-dev
    
        // webpack.config.js
        const path = require('path');
        const VueLoaderPlugin = require('vue-loader/lib/plugin')
    
        module.exports = (env, argv) => {
            const devMode = argv.mode !== 'production'
            return {
                entry: [
                    "babel-polyfill",
                    path.join(__dirname, './src/main.js')
                ],
                module: {
                    rules: [
                        // ...
                        // 解析vue
                        {
                            test: /.vue$/,
                            loader: 'vue-loader',
                            options: {
                                loaders: {}
                            }
                        },
                        // 处理scss
                        {
                            test: /.scss$/,
                            use: [
                                devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
                                'css-loader',
                                'postcss-loader',
                                'sass-loader',
                            ]
                        }
                    ]
                },
                plugins: [
                    // ...
                    new VueLoaderPlugin()
                ]
            }
        };
    

    一个简易的 vue-cli 也搭建完成,如果你想看完整代码

    参考资源

  • 相关阅读:
    解决VS2005 远程工具无法通过同步软件连接S5pv210 样机的问题
    java.util.concurrent 多线程框架线程池编程(三)
    线程池java.util.concurrent 多线程框架(二)
    java.util.concurrent 多线程框架线程池编程(一)
    java.util.concurrent 多线程框架线程池编程(四)
    Box2D学习笔记(2)
    Box2D学习笔记(1)
    ASP.NET页面防止刷新
    C#中跨数据库增删改的事务控制
    .NET(C#)开源代码分析
  • 原文地址:https://www.cnblogs.com/kkdn/p/9270591.html
Copyright © 2011-2022 走看看