sonhanguyen
11/12/2017 - 4:13 AM

react typescript scratchpad

react typescript scratchpad

module.exports = {
  type: 'react-app',
  webpack: {
    extra: {
      resolve: {
        extensions: ['.js', '.jsx', '.json', '.tsx', '.ts' ]
      },
      module: {
        rules: [
          { test: /\.jsx|tsx?$/, exclude: /node_modules/,
            use: 'awesome-typescript-loader'
          }
        ]
      }
    }    
  }
}

const package = {
  json: {
    name: '',
    version: '',
    devDependencies: {
      "reflect-metadata": "^0.1.10",
      "@types/node": "^8.0.28",
      "@types/react": "^16.0.22",
      "awesome-typescript-loader": "^3.2.3",
      "nwb": "0.18.x",
      "typescript": "^2.5.2"
    }
  }
}

const tsconfig = {
  json: {
    compilerOptions: {
      allowJs: true,
      sourceMap: true,
      emitDecoratorMetadata: true,
      experimentalDecorators: true,
      jsx: "react",
      forceConsistentCasingInFileNames: true,
      types: [ "node" ],
      target: "es5",
      lib: ["es2017", "dom"]
    }
  }
}

const index = {
  js($main) {
    const App = require($main)
    const { render } = require('react-dom')
    
    function mount(mountPoint = document.querySelector('#app')) {
      const vnode = require('react').createElement(App)
      render(vnode, mountPoint)
    }

    mount()
    module.hot && module.hot.accept($main, mount)
  }
}

const { execSync } = require('child_process')
if (require.main == module) {
  const fs = require('fs')
  if (!fs.existsSync('src')) fs.mkdirSync('src')
  const files = {
    'package.json': package.json,
    'tsconfig.json': tsconfig.json,
    'src/index.html': '<div id=app>',
    'src/index.js': index.js,
  }
  const replacements = { $main: `'../${process.argv[2]}'` }
  Object.keys(files).map((file) => {
    let toWrite = files[file]
    switch (typeof toWrite) {
      case 'object': toWrite = JSON.stringify(toWrite, null, '\t'); break
      case 'function':
        toWrite = toWrite.toString()
        toWrite.match(/\$[^,\)]+/g).map(toReplace => toWrite =
          toWrite.replace(RegExp('\\' + toReplace, 'g'), replacements[toReplace])
        )
        toWrite = toWrite.substring(toWrite.indexOf`{` + 1)
        toWrite = toWrite.substring(0, toWrite.length - 1)      
    }
    fs.writeFileSync(file, toWrite)
  })
  if (!require('./package')) $('npm i')
  const { sep } = require('path')
  $(`${String(execSync('npm bin')).trim()}${sep}nwb serve-react-app --install --reload`)
}

function $(cmd) { execSync(cmd, { stdio: [0, 1, 2] }) }