• 从零配置webpack(react+less+typescript+mobx)


    本文目标

    从零搭建出一套支持react+less+typescript+mobx的webpack配置

    最简化webpack配置

    首页要初始化yarn和安装webpack的依赖

    yarn init -y
    yarn add webpack webpack-cli -D

    根目录下新建webpack.config.js文件,内容如下

    const path = require('path');
    
    module.exports = {
        mode: 'development',
        // 入口 这里应用程序开始执行
        entry: path.resolve(__dirname, 'src/index.tsx'),
        // 出口 
        output: {
            // 输出文件的目标路径
            path: path.resolve(__dirname, 'dist'),
            // 输出的文件名
            filename: 'bundle.js',
            // 输出解析文件的目录。静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径
            publicPath: '/'
        }
    }

    使用命令进行打包

    webpack --mode production

    另外亦可以将命令配置到 package.json 中的 scripts 字段

     

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

    执行命令 yarn build 即可打包

    使用模版html

    html-webpack-plugin 插件 可以指定template模板文件,将会在output目录下,生成html文件,并引入打包后的js.

     

    安装依赖

     

    yarn add html-webpack-plugin -D

    在webpack.config.js增加plugins配置

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        //...other code
        plugins: [
            new HtmlWebpackPlugin({
                template: path.resolve(__dirname, 'src/index.html')
            })
        ]
    }

    html-webpack-plugin 插件 还支持title、minify、filename等其他参数

    配置webpack-dev-server

    webpack-dev-server提供了一个简单的Web服务器和实时热更新的能力,有助于开发。

    安装依赖

    yarn add webpack-dev-server -D

    在webpack.config.js中增加devServer配置

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        //...other code
        devServer: {
            hot: true,
            port: 3000,
            open: true,
            contentBase: path.resolve(__dirname, 'dist'),
            // 开发模式下写/就行啦
            publicPath: '/',
        }
    }

    在 package.json 的 scripts 字段中增加 start模式 

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

    这样我们就可以通过yarn start来启动服务啦

    官网devServer

    链接Webpack中publicPath详解

    支持加载css文件

    通过使用不同的 style-loader 和 css-loader, 可以将 css 文件转换成js    文件类型。

     

    安装依赖

    yarn add style-loader css-loader -D

    在webpack.config.js中增加loader配置

    module.exports = {
        //other code
        module: {
            rules: [
                {
                    test: /.css/,
                    use: ['style-loader', 'css-loader'],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                }
            ]
        }
    }

    loader 可以配置以下参数:

    • test: 匹配处理文件的扩展名的正则表达式
    • use: loader名称
    • include/exclude: 手动指定必须处理的文件夹或屏蔽不需要处理的文件夹
    • query: 为loader提供额外的设置选项

    支持图片加载

    需要引入两个loader

    • file-loader: 解决CSS等文件中的引入图片路径问题
    • url-loader: 当图片小于limit的时候会把图片Base64编码,大于limit参数的时候还是使用file-loader进行拷贝

    如果希望图片存放在单独的目录下,那么需要指定outputPath

     

    安装依赖

    yarn add url-loader file-loader -D

    在 webpack.config.js 中增加 loader 的配置(增加在 module.rules 的数组中)。

     

    module.exports = {
        //other code
        module: {
            rules: [
                {
                    test: /.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                limit: 8192,
                                outputPath: 'images'
                            }
                        }
                    ]
                }
            ]
        }
    } 

     

    支持编译less

    很多前端都喜欢写less,所以支持less也是需要的。(sass配置方法基本相同)

    安装依赖

    yarn add less less-loader -D

    在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。

     

    module.exports = {
        //other code
        module: {
            rules: [
                {
                    test: /.less/,
                    use: ['style-loader', 'css-loader', 'less-loader'],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
            ]
        }
    }        
     

    支持转义 ES6/ES7/JSX(react)

    安装ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。

     

    yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread -D

    在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。

    module.exports = {
        //other code
        module: {
            rules: [
                {
                    test: /.jsx?$/,
                    use: [
                        {
                            loader: 'babel-loader',
                            options: {
                                presets: ['@babel/preset-env', '@babel/react'],
                                plugins: [
                                    [
                                      "@babel/plugin-proposal-decorators", 
                                      { "legacy": true }
                                    ]
                                ]
                            }
                        }
                    ],
                    include: path.resolve(__dirname, 'src'),
                    exclude: /node_modules/
                },
            ]
        }
    }

    压缩JS文件

    安装依赖

    yarn add uglifyjs-webpack-plugin -D

    在 webpack.config.js 中增加 optimization 的配置

     

    const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');
    
    module.exports = {
        //other code
        optimization: {
            minimizer: [
                new UglifyWebpackPlugin({
                    parallel: 4
                })
            ]
        }
    }

    分离出CSS

    因为CSS的下载和JS可以并行,当一个HTML文件很大的时候,可以把CSS单独提取出来加载

     

    安装依赖

     

    yarn add mini-css-extract-plugin -D

    在 webpack.config.js 中增加 plugins 的配置,并且将 'style-loader' 修改为 { loader: MiniCssExtractPlugin.loader}。CSS打包在单独目录,那么配置filename。

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
    module.exports = {
        //other code
        module: {
            rules: [
                {
                    test: /.css/,
                    use: [{ loader: MiniCssExtractPlugin.loader}, 'css-loader'],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
                {
                    test: /.less/,
                    use: [{ loader: MiniCssExtractPlugin.loader }, 'css-loader', 'less-loader'],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
            ]
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name].css'
            })
        ]
    }

    压缩CSS文件

    安装依赖

    yarn add optimize-css-assets-webpack-plugin -D

    在 webpack.config.js 中的 optimization 中增加配置

     

    const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    
    module.exports = {
        //other code
        optimization: {
            minimizer: [
                new OptimizeCssAssetsWebpackPlugin()
            ]
        }
    }

    支持react和mobx

    安装react依赖

    yarn add react react-dom 

    安装mobx依赖

    yarn add mobx mobx-react

    支持typescript

    安装依赖

    yarn add typescript awesome-typescript-loader -D

    安装react的类型依赖(否则会有命名空间和.d.ts相关报错)

    yarn add @types/react @types/react-dom

    在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。

    module.exports = {
        //other code
        module: {
            rules: [
                 {
                    test: /.(tsx|ts)?$/,
                    loader: "awesome-typescript-loader",
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                }
            ]
        }
    }

    在根目录下添加tsconfig.json

    {
      "compilerOptions": {
        "baseUrl": ".",
        "outDir": "build/dist",
        "module": "esnext",
        "target": "es5",
        "lib": ["es6", "dom"],
        "sourceMap": true,
        "allowJs": true,
        "jsx": "react",
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "rootDir": "./",
        "forceConsistentCasingInFileNames": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noImplicitAny": false,
        "importHelpers": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": false,
        "allowSyntheticDefaultImports": true
      },
      "exclude": [
        "node_modules",
        "build",
        "scripts",
        "acceptance-tests",
        "webpack",
        "jest",
        "src/setupTests.ts"
      ]
    }

    在根目录下添加tslint.json

    {
      "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
      "rules": {
        "no-empty-interface":false,
        "no-empty-block":false,
        "no-unused-expression":false,
        "object-literal-sort-keys":false,
        "no-empty":false,
        "semicolon": [false, "always"],
        "no-default-export": false,
        "member-access": true,
        "ordered-imports": false,
        "import-sources-order": "any",
        "named-imports-order": "any",
        "interface-over-type-literal":false,
        "jsx-no-lambda":false,
        "variable-name": [
          true,
          "ban-keywords",
          "check-format",
          "allow-leading-underscore",
          "allow-trailing-underscore",
          "allow-pascal-case",
          "allow-snake-case"
        ],
        "no-console": false,
        "no-angle-bracket-type-assertion": false,
        "jsx-no-string-ref":false,
        "prefer-for-of":false,
        "member-ordering":false,
        "only-arrow-functions":false,
        "object-literal-shorthand":false
      },
      "linterOptions": {
        "exclude": [
          "config/**/*.js",
          "node_modules/**/*.ts",
          "coverage/lcov-report/*.js"
        ]
      },
      "strict": false
    }

    打包前先清空输出目录

    安装依赖

    yarn add clean-webpack-plugin -D

    在 webpack.config.js 中增加 plugins 的配置

    const {CleanWebpackPlugin} = require('clean-webpack-plugin');
    
    module.exports = {
        //other code
        plugins: [
            new CleanWebpackPlugin()
        ]
    }

    ( 注意3.0版本的clean-webpack-plugin有大改动,需要通过构造函数取出CleanWebpackPlugin再用 )

    至此,webpack配置已经基本能满足react+less+typescript+mobx开发需求。

     

    完整webpack.config.js和package.json文件

    webpack.config.js文件

    const path = require('path');
    // 打包html的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    // 压缩JS的插件
    const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');
    // 分离css文件
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    // 打包前先清空输出目录
    const {CleanWebpackPlugin} = require('clean-webpack-plugin');
    
    module.exports = {
        mode: 'development',
        // 入口 这里应用程序开始执行
        entry: path.resolve(__dirname, 'src/index.tsx'),
        // 出口
        output: {
            // 所有输出文件的目标路径
            path: path.resolve(__dirname, 'dist'),
            // 输出的文件名
            filename: 'bundle.js',
            // 输出解析文件的目录,url 相对于 HTML 页面, publicPath 上线时配置的是cdn的地址。
            // 静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径
            publicPath: './'
        },
        devServer: {
            hot: true,
            port: 3000,
            open: true,
            contentBase: path.resolve(__dirname, 'dist'),
            publicPath: '/',
            // stats: 'none'
        },
        module: {
            rules: [
                /*
                * 支持css
                * 通过使用不同的 style-loader 和 css-loader, 可以将 css 文件转换成JS文件类型。
                * */
                {
                    test: /.css/,
                    // use: ['style-loader', 'css-loader'],
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        'css-loader'
                    ],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
                /*
                * 支持编译less和sass
                * */
                {
                    test: /.less/,
                    // use: ['style-loader', 'css-loader', 'less-loader'],
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        'css-loader',
                        'less-loader'
                    ],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
                /*
                * 支持加载图片
                * file-loader: 解决CSS等文件中的引入图片路径问题
                * url-loader: 当图片小于limit的时候会把图片Base64编码,大于limit参数的时候还是使用file-loader进行拷贝
                * */
                {
                    test: /.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                limit: 1,
                                outputPath: 'images'
                            }
                        }
                    ]
                },
                /*
                * 支持转义 ES6/ES7/JSX  ,支持react
                * ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。
                * */
                {
                    test: /.jsx?$/,
                    use: [
                        {
                            loader: "babel-loader",
                            options: {
                                presets: ['@babel/preset-env', '@babel/react'],
                                plugins: [
                                    [
                                        "@babel/plugin-proposal-decorators",
                                        // "@babel/plugin-proposal-class-properties",
                                        {
                                            "legacy": true
                                        }
                                    ]
                                ]
                            }
                        }
                    ],
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                },
                /*
               * 支持转义 支持typescript
               * ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。
               * */
                {
                    test: /.(tsx|ts)?$/,
                    loader: "awesome-typescript-loader",
                    exclude: /node_modules/,
                    include: path.resolve(__dirname, 'src')
                }
            ]
        },
        optimization: {
            minimizer: [
                new UglifyWebpackPlugin({
                    parallel: 4
                })
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: path.resolve(__dirname, 'public/index.html')
            }),
            new MiniCssExtractPlugin({
                filename:'css/[name].css'
            }),
            new CleanWebpackPlugin()
        ]
    };

    package.json文件

     

    {
      "name": "webpack_cli",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "scripts": {
        "start": "webpack-dev-server --mode development",
        "build": "webpack --mode production"
      },
      "devDependencies": {
        "@babel/core": "^7.5.5",
        "@babel/plugin-proposal-decorators": "^7.4.4",
        "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
        "@babel/preset-env": "^7.5.5",
        "@babel/preset-react": "^7.0.0",
        "@types/react": "^16.9.2",
        "@types/react-dom": "^16.8.5",
        "awesome-typescript-loader": "^5.2.1",
        "babel-loader": "^8.0.6",
        "clean-webpack-plugin": "^3.0.0",
        "css-loader": "^3.2.0",
        "file-loader": "^4.2.0",
        "html-webpack-plugin": "^3.2.0",
        "less": "^3.10.1",
        "less-loader": "^5.0.0",
        "mini-css-extract-plugin": "^0.8.0",
        "optimize-css-assets-webpack-plugin": "^5.0.3",
        "style-loader": "^1.0.0",
        "typescript": "^3.5.3",
        "uglifyjs-webpack-plugin": "^2.2.0",
        "url-loader": "^2.1.0",
        "webpack": "^4.39.2",
        "webpack-cli": "^3.3.7",
        "webpack-dev-server": "^3.8.0"
      },
      "dependencies": {
        "mobx": "^5.13.0",
        "mobx-react": "^6.1.3",
        "react": "^16.9.0",
        "react-dom": "^16.9.0"
      }
    }

    学习更多webpack配置请进入webpack官网 webpack官网链接

    本文配置将持续升级优化

  • 相关阅读:
    爬虫
    vue进级
    el-upload加header
    上传图片到服务器报错 {errMsg: "uploadFile:fail ssl hand shake error"}
    【Node.js】论一个低配版Web实时通信库是如何实现的1( WebSocket篇)
    【Node.js】 bodyparser实现原理解析
    【JavaScript】EventEmitter的前端实现
    【JavaScript】当我们尝试用JavaScipt测网速
    git命令
    【Java】利用注解和反射实现一个"低配版"的依赖注入
  • 原文地址:https://www.cnblogs.com/piaobodewu/p/11374475.html
Copyright © 2020-2023  润新知