quick-react-webpack

webpack for react

Usage no npm install needed!

<script type="module">
  import quickReactWebpack from 'https://cdn.skypack.dev/quick-react-webpack';
</script>

README

quick-react-webpack

quick webpack for react(modify from new version create-react-app:eject for better custom for business)

install&&cli


npm i quick-react-webpack -D

//in package.json
{
  "scripts":{
    "dev":"qr development",
    "build":"qr production"
  }
}

//before npm run dev/build,need config appConfig.js in current directory

//and also can use script to run
{
  "dev": "node ./env/dev.js",
  "build": "node ./env/prod.js",
}

//in ./env/dev.js
 require('quick-react-wepback').development();
 //in ./env/prod.js
 require('quick-react-wepback').production();

example

//package.json
 "scripts": {
    "start": "qr development",
    "build": "qr production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
 "dependencies": {
    "@hot-loader/react-dom": "^16.9.0",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-router": "^5.1.2",
    "react-router-dom": "^5.1.2"
  },
  "devDependencies": {
    "quick-react-webpack": "^2.2.3"
  }

//./src/main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<div><App/></div>, document.getElementById('root'));

//./src/App.js
import React from 'react';
import { hot } from 'react-hot-loader';
class App extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <div>App</div>;
  }
}
if (
  process.env.NODE_ENV === 'development' &&
  [true, 'true'].indexOf(process.env.HOT) !== -1
) {
  App = hot(module)(App);
}
export default App;


// ./appConfig.js
module.exports = {
  // analyze:true,
  port: 3000,
  entryIndex: './src/main.js',
  buildDir: './dist',
  appHtml: './src/index.html',
  hot: true
};

//./src/index.html
/*
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id='root'></div>
</body>
</html>
*/

appConfig.js

default appConfig.js position is in current project root directory.This config support scss,less,svg,less,json,xml,ts,js file type default.write tsconfig.json in root directory if use ts project

basic config

module.exports={

port: 3000,

entryIndex: './src/main.js', //root js file,or object:{},or array:[]

appHtml: './src/index.html', //html position,or entry which follow by entryIndex,or [] by custom define

useTypescript:true/false,//default false

htmlDir: './src/index.html', //is appHtml ==='entry' use this for basic directory

htmlTemplate: './src/index.html', //is appHtml ==='entry' use this for template first,otherwise use entry content

buildDir: './dist', //build directory

buildDirWrap: true, //default false,if use true,will package just like ./dist/packageName/build code

hot: true, //whether use hot reload in development

useDefaultPostcss:true/false//default is true,use inner simple postcss

rewrites:[{ from: //somepath/(somepath)(/.*)?$/, to: '/somepath.html'}]

assetsPublicPath: 'https://a.com', //will inject path to static resource,for example <img src={someimg from './.../a.png'}> will result to https://a.com/a.png

serverContentBase:'',//webpack server assets base dir

buildAssetsDir: 'assets', //will copy the static resources to aim directory in production env

https: false, //or config webpack https in development

pageEnv: { A: 1, B: 2 }, //will inject process.env.A,process.env.B in the project,in html use <%= htmlWebpackPlugin.options.env.VAR %>,in js use process.env.VAR

mock: true, //default is false,use true to mock current directory

mockPath: './mock', //will mock file in mock directory,if ajax request just like /a/b, can use ./mock/a/b.json or ./mock/a/b.js to return data,in js code just like module.exports=function(req,res){res.send(...);}

mockOneFile: true, //if use this config,don't need to write many mock file in mock directory,just add index.js in mock directory, and put module.exports=function(req,res){if(req.url==='a/b'){res.send();}else if(req.url==='x/y'){...}}

themeVariables: { 'success-color': '#268543' }, //only use for less.

proxy: 'https://a.com', //default is false,use this to proxy /x/y ajax request to https://a.com/x/y

filename: {

js: 'scripts/[name].[contenthash].js', css: 'css/[name].[contenthash].css' },//default if {js:'scripts/main.js',css:'css/main.css'}

split: [ { name: 'react-dom', path: /node_modules/react-dom/ } ], //default false,will split one js to multiple js,and the order is from one to last

include: [/some-package-path/], //default empty,only watch src directory.if you want to watch the file in node_modules,can add in the include array

babelrc: { plugins: [ [ 'babel-plugin-import', { libraryName: 'antd', style: true } ] ] }, //inject custom babel to project.Also support babel file in root directory tsOnlyTranspile:false,//default false,if true,will not check error of ts webpack: { alias() { return { Utils: path.resolve('./src/app/utils') }; }, plugins(){ return [ ... ] } } //default is empty,added config can't cover default plugin,just extend it }

other config in appConfig.js

after compiler down,use callback to custom logic

{
   ...(env === 'production'
    ? {
        callback: () => {
          console.log('compiler donw');
        }
      }
    : {})
}

sometimes, want to see dependent version in builded js,inject dependent version(this function only support current directory/node_modules),only use production.

{
  versionInject: {
  test: /main.[\w\.]\*js\$/,//default is /\.js/
  data: [ 'react', 'some-package']
  }
}

will create content in footer position

/*
 react:version:16.12.0
 some-package:version:1.0.0
*/

inject content to html,this can help you to inject some data by the async backend service in init time && production extra data.

{
  htmlInject: {
    script: `console.log('example')`,//inject script to body
    change: async opt => {//custom html
      let { $, request, html,cheerio } = opt;
      // let data=await request({url: 'http://localhost:3009/test',method:'get'});
      // data:{status,body,headers}
      $('head').append(`<script>console.log('example');</script>`);
      return $.html();
    },
    style: 'body{background:red;}'//inject script to head
  }
}

//$ used by cheerio

//request is a wrap method by node-fetch

request({
  url: string,
  method: 'post',
  headers: {},
  body: { a: 1, b: 2 },
});

//form x-www-form-urlencoded
request({
  url: string,
  method: 'post',
  headers: {},
  body: { a: 1, b: 2 },
  bodyType: 'formParameters',
});

//form-data
request({
  url: string,
  method: 'post',
  headers: {},
  body: { a: 1, b: 2 },
  bodyType: 'formData',
});

//get query
request({
  url: string,
  method: 'get',
  headers: {},
  query: {
    a: 1,
    b: 2,
  },
});