美文网首页
webpack4+react多页应用

webpack4+react多页应用

作者: 沐雨芝录 | 来源:发表于2019-04-04 15:57 被阅读0次

前言

上篇内容从零开始搭建webpack4的react项目,这里只说多页相关的配置。上篇文章地址:webpack4+react从零开始搭建项目

先看下多页的文件目录结构:


image.png

这里我们有一个公用的html模板,app1和app2的两个多页文件。

webpack.config.js配置主要更改两个部分:
一、entry里面是键值对结构:

module.exports = (env, argv) => {
    return {
        entry: {
          app1: './src/app1/index.js',
          app2: './src/app2/index.js'
        }
    }
}

看过我上篇的同学肯定会问,上篇不是数组嘛,还能加babel-polyfill,所以也可以是这种配置:

module.exports = (env, argv) => {
    return {
        entry: {
          entry: {
            app1: ["babel-polyfill", './src/app1/index.js'],
            app2: ["babel-polyfill", './src/app2/index.js']
        }
    }
}

二、plugins里的new HtmlWebpackPlugin变成数组形式:

module.exports = (env, argv) => {
  return {
    plugins: [
      // ...
      new HtmlWebpackPlugin({
        chunks:['app1'], //添加引入的js,也就是entry中的key
        filename:'app1.html', // 输出页面,如http://localhost:3000/app1.html就能看到第一个模板
        hash:true,
        title:'第一个页面',
        template: './public/index.html' //模板地址
      }),
      new HtmlWebpackPlugin({
          chunks:['app2'], //添加引入的js,也就是entry中的key
          filename:'app2.html', // 输出页面
          hash:true,
          title:'第二个页面',
          template: './public/index.html' //模板地址
      })
    ]
  }
}

简单配置完毕,如果想动态配置,可以这么改,直接贴出所有配置,主要是这两个函数:,我觉得怎么封装好理解是自己的事情,建议大家最好自己封装一套,最重要的方法就一个glob.sync('src/**/index.js')获取src下第一层级文件夹下的index.js。

const webpack = require('webpack');//引入webpack
const path = require('path');//引入nodejs路径模块,处理路径用的
const glob = require('glob');//glob,这个是一个全局的模块,动态配置多页面会用得着
const HtmlWebpackPlugin = require('html-webpack-plugin'); //这个是通过html模板生成html页面的插件,动态配置多页面用得着
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 清除打包的源文件,再打包,避免文件重复
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//分离css,webpack4推荐的分离css的插件
const autoprefixer = require('autoprefixer');//给css自动加浏览器兼容性前缀的插件
const os = require('os');//这个nodejs模块,会帮助我们获取本机ip
const portfinder = require('portfinder');//这个帮助我们寻找可用的端口,如果默认端口被占用了的话
const fs = require('fs');//处理文件用的

//动态加时间戳,发布不需要刷新浏览器
function stamp(){
  var date = new Date();
  date = Date.parse(date);
  return date;
}

//端口占用动态+1
var ports = fs.readFileSync('./port.json', 'utf8');
ports = JSON.parse(ports);
portfinder.basePort = "3000";
portfinder.getPort(function(err, port) {
    ports.data.port = port;
    ports = JSON.stringify(ports,null,4);
    fs.writeFileSync('./port.json',ports);
});

//获取本机ip
function getIPAdress(){  
  const interfaces = os.networkInterfaces();  
  for(let devName in interfaces){  
      const iface = interfaces[devName];  
      for(let i=0;i<iface.length;i++){  
          const alias = iface[i];  
          if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){  
              return alias.address;  
          }  
      }  
  }  
} 

module.exports = (env, argv) => {
  const devMode = argv.mode !== 'production'

  const webpackConfig = {
    entry: {},
    output:{
      path:path.resolve(__dirname, './dist/'),
      filename:`[name]-${stamp()}.js`
    },
    //设置开发者工具的端口号,不设置则默认为3000端口
    devServer: {
      port: ports.data.port, //端口号
      overlay: true, // 开启错误调试,
      hot: true,  //是否开启hot-module-replacement
      https: false, // 如果需要用https请开启,如http2
      compress:false, //是否启用 gzip 压缩。boolean 为类型,默认为 false
      open: false, // 启动且第一次构建完时自动用你系统上默认的浏览器去打开要开发的网页。
      stats: "errors-only", // 只展示错误信息,避免大量无用日志
      host: getIPAdress()  //获取本机器ip
    },
    module:{
      rules:[
        {
          test:/\.(js|jsx)$/,
          exclude:/node_modules/,
          use: {
            loader: "babel-loader"
          }
        },
        {
          test: /\.html$/,
          use: [{
              loader: "html-loader",
              options: {
                  minimize: true
              }
          }]
      },
      {
          test: /\.css$/,
          use: [
              devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
              'css-loader',
              {
                    loader: "postcss-loader",
                    options: {
                          plugins: [
                              require("autoprefixer") /*在这里添加*/
                          ]
                    }
              }
          ]
      },
      {
          test: /\.less$/,
          use: [
              devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
              'css-loader',
              'less-loader',
              {
                  loader: "postcss-loader",
                  options: {
                      plugins: [
                          require("autoprefixer") /*在这里添加*/
                      ]
                  }
              }
          ]
      },
      {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
              'file-loader'
          ]
      }
        
      ]
    },
    plugins: [
      new CleanWebpackPlugin(
        ['dist'],  
        {
          root: __dirname,              
          verbose: true,              
          dry:   false              
        }
      ),
      new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].css"
      })
    ]
  }

  // 获取指定路径下的入口文件
  function getEntries(globPath) {
    const files = glob.sync(globPath),
    entries = {};
    files.forEach(function(filepath) {
      const split = filepath.split('/');
      const name = split[split.length - 2];
      entries[name] = './' + filepath;
    });
    return entries;
  }
      
  const entries = getEntries('src/**/index.js');
  
  Object.keys(entries).forEach(function(name) {
    webpackConfig.entry[name] = entries[name]; // entry拼接对象键值对
    const plugin = new HtmlWebpackPlugin({
      filename: name + '.html',
      template: './public/index.html',
      inject: true,
      chunks: [name]
    });
    webpackConfig.plugins.push(plugin); //new HtmlWebpackPlugin数组 
  })

  return webpackConfig
};

这里多了三个方法:
1、动态加时间戳 stamp(),如果我们发布不打tag,那么浏览器就有缓存,每次发布,就需要强刷页面,很可能被提成bug,这里可以添加时间戳,然后在output方法里面加入即可

output:{
      path:path.resolve(__dirname, './dist/'),
      filename:`[name]-${stamp()}.js`
    }

2、获取本机ip,我们之前看页面是localhost,如果想分享,就需要ipconfig,我们自动获取,方便了一些。
第一步根目录创建port.json

{
    "data": {
        "port": 3000
    }
}

第二步在webpack.config.js写好方法:

var ports = fs.readFileSync('./port.json', 'utf8');
ports = JSON.parse(ports);
portfinder.basePort = "3000";
portfinder.getPort(function(err, port) {
    ports.data.port = port;
    ports = JSON.stringify(ports,null,4);
    fs.writeFileSync('./port.json',ports);
});

第三步webpack.config.js配置devServer

devServer: {
      port: ports.data.port, //端口号

3、获取本机ipgetIPAdress,配置devServer

devServer: {
  host: getIPAdress()  //获取本机器ip
}

github地址:https://github.com/muyu-zhilu/webpack-react-multipage

相关文章

  • webpack4+react多页应用

    前言 上篇内容从零开始搭建webpack4的react项目,这里只说多页相关的配置。上篇文章地址:webpack4...

  • vue-router考察问题

    单页应用和多页应用的区别 多页应用MPA单页应用SPA应用组成由多个完成页面构成一个外部显示的页面 + 多个局部页...

  • 单页应用 VS 多页应用

  • 单页应用多页应用对比

    webx5单页模式打开方式:justep.shell.showpage();多页模式打开方式:window.loa...

  • 单页应用和多页应用

    单页面应用(SinglePage Web Application,SPA) 一个项目中只有一个完整的html页面,...

  • 单页应用与多页应用

    一、单页应用 利用Vue开发的应用是单页面应用,在url变化时,js会感知到,然后动态地将当前页面上的内容清除...

  • 前端工程化

    场景 前后端完全分离前后端分离还看是单则应用还是多页应用单页应用用webpack,比较强势。 多页应用用webpa...

  • MPA(多页应用)、SPA(单页应用)

    一、MPA、SPA两者定义 MPA MPA(mutiple-page application),翻译过来就是多页面...

  • vue多页应用

    vue如何将单页面改造成多页面应用 vue单页多页的开发环境配置+vue的开发思路

  • 第一章 React 介绍

    本章内容 多页应用开发模式的缺点 单页应用开发模式的优点 单页应用开发模式的主要问题 React 如何解决单页应用...

网友评论

      本文标题:webpack4+react多页应用

      本文链接:https://www.haomeiwen.com/subject/ifjfiqtx.html