资讯专栏INFORMATION COLUMN

webpack4 + react 搭建多页面应用

wushuiyong / 2170人阅读

摘要:升级到之后还没好好的同步一个可实用的架子,接下来用来搭建一个简单的的多界面应用,废话不说直接撸码创建工程目录结构工程目录结构配置安装依赖引入打开浏览器配置文件合并基础配置一些路径配置设置开发环境

webpack 升级到4之后还没好好的同步一个可实用的webpack架子,接下来用webpack4来搭建一个简单的react的多界面应用,废话不说 直接撸码
创建工程
$ mkdir demo && cd demo
$ npm init -y
目录结构
![工程目录结构][1]

webpack 配置
安装react + babel 依赖

$ npm i -S react@16.3.0 react-dom@16.3.0

$ npm i -D webpack@4.4.1 webpack-cli@2.0.13 webpack-dev-server@3.1.1 webpack-merge@4.1.2 babel-cli@6.26.0 babel-preset-env@1.6.1 babel-preset-react@6.24.1 babel-preset-react-hmre@1.1.1 babel-loader@7.1.4 file-loader@1.1.11 url-loader@1.0.1

webpack.base.conf.js(config -> webpack)
const entry = require("./webpack.entry.conf");
const newEntry = {};
for (let name in entry) {
    newEntry[name] = entry[name][0]
}
let config = {
    entry: newEntry,
    resolve: {
        extensions: [".js", ".json", ".jsx", ".css", ".pcss"],
    }
};
module.exports = config;
webpack.dev.conf.js
const webpack = require("webpack");//引入webpack
const opn = require("opn");//打开浏览器
const merge = require("webpack-merge");//webpack配置文件合并
const path = require("path");
const baseWebpackConfig = require("./webpack.base.conf");//基础配置
const webpackFile = require("./webpack.file.conf");//一些路径配置
const eslintFormatter = require("react-dev-utils/eslintFormatter");

let config = merge(baseWebpackConfig, {
    /*设置开发环境*/
    mode: "development",
    output: {
        path: path.resolve(webpackFile.devDirectory),
        filename: "js/[name].js",
        chunkFilename: "js/[name].js",
        publicPath: ""
    },
    optimization: {
        runtimeChunk: {
            name: "manifest"
        },
        // 包拆分
        splitChunks: {
            cacheGroups: {
                common: {   // 项目的公共组件
                    chunks: "initial",
                    name: "common",
                    minChunks: 2,
                    maxInitialRequests: 5,
                    minSize: 0
                },
                vendor: {   // 第三方组件
                    test: /node_modules/,
                    chunks: "initial",
                    name: "vendor",
                    priority: 10,
                    enforce: true
                }
            }
        }
    },
    plugins: [
        /*设置热更新*/
        new webpack.HotModuleReplacementPlugin(),
    ],
    module: {
        rules: [
            {
                test: /.(js|jsx)$/,
                use: [
                    "babel-loader",
                    "cache-loader",
                ],
                include: [
                    path.resolve(__dirname, "../../app"),
                    path.resolve(__dirname, "../../entryBuild")
                ],
                exclude: [
                    path.resolve(__dirname, "../../node_modules")
                ],
            },
            {
                test: /.(css|pcss)$/,
                loader: "style-loader?sourceMap!css-loader?sourceMap!postcss-loader?sourceMap",
                exclude: /node_modules/
            },
            {
                test: /.(png|jpg|gif|ttf|eot|woff|woff2|svg|swf)$/,
                loader: "file-loader?name=[name].[ext]&outputPath=" + webpackFile.resource + "/"
            },
            {
                test: /.(js|jsx)$/,
                enforce: "pre",
                use: [
                    {
                        options: {
                            formatter: eslintFormatter,
                            eslintPath: require.resolve("eslint"),
                            // @remove-on-eject-begin
                            baseConfig: {
                                extends: [require.resolve("eslint-config-react-app")],
                            },
                            //ignore: false,
                            useEslintrc: false,
                            // @remove-on-eject-end
                        },
                        loader: require.resolve("eslint-loader"),
                    },
                ],
                include: [
                    path.resolve(__dirname, "../../app")
                ],
                exclude: [
                    path.resolve(__dirname, "../../node_modules")
                ],
            }
        ]
    },
    /*设置api转发*/
    devServer: {
        host: "0.0.0.0",
        port: 8080,
        hot: true,
        inline: true,
        contentBase: path.resolve(webpackFile.devDirectory),
        historyApiFallback: true,
        disableHostCheck: true,
        proxy: [
            {
                context: ["/api/**", "/u/**"],
                target: "http://10.8.200.69:8080/",
                secure: false
            }
        ],
        /*打开浏览器 并打开本项目网址*/
        after() {
            opn("http://localhost:" + this.port);
        }
    }
});
module.exports = config;
webpack.prod.conf.js
const path = require("path");
const merge = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const baseWebpackConfig = require("./webpack.base.conf");
const webpackFile = require("./webpack.file.conf");
const entry = require("./webpack.entry.conf");
const webpackCom = require("./webpack.com.conf");

let config = merge(baseWebpackConfig, {
    /*设置生产环境*/
    mode: "production",
    output: {
        path: path.resolve(webpackFile.proDirectory),
        filename: "js/[name].[chunkhash:8].js",
        chunkFilename: "js/[name]-[id].[chunkhash:8].js",
    },
    optimization: {
        //包清单
        runtimeChunk: {
            name: "manifest"
        },
        //拆分公共包
        splitChunks: {
            cacheGroups: {
                common: { //项目公共组件
                    chunks: "initial",
                    name: "common",
                    minChunks: 2,
                    maxInitialRequests: 5,
                    minSize: 0
                },
                vendor: {   //第三方组件
                    test: /node_modules/,
                    chunks: "initial",
                    name: "vendor",
                    priority: 10,
                    enforce: true
                }
            }
        }
    },
    plugins: [
        // extract css into its own file
        new ExtractTextPlugin("css/[name].[md5:contenthash:hex:8].css"),
        // Compress extracted CSS. We are using this plugin so that possible
        // duplicated CSS from different components can be deduped.
        new OptimizeCSSPlugin({
            assetNameRegExp: /.css$/g,
            cssProcessor: require("cssnano"),
            cssProcessorOptions: {
                discardComments: {removeAll: true},
                // 避免 cssnano 重新计算 z-index
                safe: true
            },
            canPrint: true
        }),
    ],
    module: {
        rules: [
            {
                test: /.(js|jsx)$/,
                use: [
                    "babel-loader",
                ],
            },
            {
                test: /.(js|jsx)$/,
                loader: "babel-loader",
                exclude: /node_modules/,
            },
            {
                test: /.(css|pcss)$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: "css-loader!postcss-loader"
                })
            },
            {
                test: /.(png|jpg|gif|ttf|eot|woff|woff2|svg)$/,
                loader: "url-loader?limit=8192&name=[name].[hash:8].[ext]&publicPath=" + webpackFile.resourcePrefix + "&outputPath=" + webpackFile.resource + "/"
            },
            {
                test: /.swf$/,
                loader: "file?name=js/[name].[ext]"
            }
        ]
    }
});
let pages = entry;
for (let chunkName in pages) {
    let conf = {
        filename: chunkName + ".html",
        template: "index.html",
        inject: true,
        title: webpackCom.titleFun(chunkName,pages[chunkName][1]),
        minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
        },
        chunks: ["manifest", "vendor", "common", chunkName],
        hash: false,
        chunksSortMode: "dependency"
    };
    config.plugins.push(new HtmlWebpackPlugin(conf));
}
/* 清除 dist */
config.plugins.push(new CleanWebpackPlugin([webpackFile.proDirectory], {root: path.resolve(__dirname, "../../"), verbose: true, dry: false}));


/* 拷贝静态资源  */
copyArr.map(function (data) {
    return config.plugins.push(data)
});


module.exports = config;
构建多界面
整体架构搭建起来之后
app -> component 

$ mkdir demo && cd demo

$ touch Index.jsx

    import React from "react";

    class Index extends React.Component {
        render() {
            return (
                
写个demo
); } } export default Index;

在config -> entry

module.exports = [
    {
        name: "index",
        path: "index/Index.jsx",
        title: "首页",
        keywords: "首页",
        description: "首页"
    },
    {
        name: "demo",
        path: "demo/Index.jsx",
        title: "demo",
        keywords: "demo",
        description: "demo"
    },
    {
        name: "demo1",
        path: "demo1/Index.jsx",
        title: "demo1",
        keywords: "demo1",
        description: "demo1"
    }
];


然后直接执行 npm run create-dev 就会在devBuild 和 entryBuild 中添加一个新的demo.html 和 demo.js

package.json

{
  "name": "webpack_es6",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors --profile --config config/webpack/webpack.dev.conf.js",
    "entry": "node config/entry/entryBuild.js",
    "devBuildHtml": "node config/webpack/webpack.devBuildHtml.conf.js",
    "create-dev": "npm run entry && npm run devBuildHtml",
    "build": "BABEL_ENV=production && webpack --progress --colors --config config/webpack/webpack.prod.conf.js",
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.3.0",
    "react-dom": "^16.3.0"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-eslint": "^8.2.2",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-react-hmre": "^1.1.1",
    "cache-loader": "^1.2.2",
    "clean-webpack-plugin": "^0.1.19",
    "copy-webpack-plugin": "^4.5.1",
    "css-loader": "^0.28.11",
    "eslint": "^4.19.1",
    "eslint-config-react-app": "^2.1.0",
    "eslint-loader": "^2.0.0",
    "eslint-plugin-flowtype": "^2.46.1",
    "eslint-plugin-import": "^2.10.0",
    "eslint-plugin-jsx-a11y": "^5.1.1",
    "eslint-plugin-react": "^7.7.0",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "file": "^0.2.2",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.1.0",
    "optimize-css-assets-webpack-plugin": "^4.0.0",
    "postcss-cssnext": "^3.1.0",
    "postcss-loader": "^2.1.3",
    "precss": "^3.1.2",
    "react-dev-utils": "^5.0.0",
    "style-loader": "^0.20.3",
    "url-loader": "^1.0.1",
    "webpack": "^4.4.1",
    "webpack-cli": "^2.0.13",
    "webpack-dev-server": "^3.1.1",
    "webpack-merge": "^4.1.2"
  },
  "eslintConfig": {
    "extends": "react-app",
    "rules": {
      "import/no-webpack-loader-syntax": 0,
      "no-script-url": 0,
      "jsx-a11y/href-no-hash": 2
    }
  }
}

开发环境小技巧
在开发环境添加cache-loader 可以提升在开发环境的编译速度

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96515.html

相关文章

  • webpack4 + react 搭建页面应用

    摘要:升级到之后还没好好的同步一个可实用的架子,接下来用来搭建一个简单的的多界面应用,废话不说直接撸码创建工程目录结构工程目录结构配置安装依赖引入打开浏览器配置文件合并基础配置一些路径配置设置开发环境 webpack 升级到4之后还没好好的同步一个可实用的webpack架子,接下来用webpack4来搭建一个简单的react的多界面应用,废话不说 直接撸码 创建工程 $ mkdir dem...

    nifhlheimr 评论0 收藏0
  • 基于webpack4.x, babel7.x 搭建页面脚手架, 简化前端开发环境配置,开箱即用,

    摘要:开箱即用的多页面脚手架基于模块化开发可复用的现代化网站感兴趣的朋友,请点个及时关注项目更新请点个项目请提特性支持前后端分离开发配置完整的打包方案支持本地开发热更新集成代码风格校验支持编写源码,编译生成生产代码内置开发环境,自动加样式前缀自 Webpack-seed 开箱即用的多页面脚手架, 基于webpack4.2x babel7.1x模块化开发可复用的现代化网站(Without Vu...

    junfeng777 评论0 收藏0
  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<