webpack4+react+typescript搭建demo
阿新 • • 發佈:2019-01-04
最近寫了個用react+webpack+typescript搭建的demo
目錄結構如下:
package.json:
{ "name": "react-webpack-cms", "version": "1.0.0", "description": "", "main": "src/index.tsx", "scripts": { "build-dev": "cross-env NODE_ENV=development webpack --config ./bin/webpack.dev.config.js --colors", "build-proc": "cross-env NODE_ENV=production webpack --config ./bin/webpack.proc.config.js --colors", "dev":"cross-env NODE_ENV=development node ./bin/dev-server.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@types/react": "^16.4.12", "@types/react-dom": "^16.0.7", "react": "^16.4.2", "react-dom": "^16.4.2" }, "devDependencies": { "autoprefixer": "^9.1.3", "babel-core": "^6.26.3", "babel-loader": "^7.1.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-es2015": "^6.24.1", "clean-webpack-plugin": "^0.1.19", "cross-env": "^5.2.0", "css-loader": "^1.0.0", "extract-text-webpack-plugin": "^4.0.0-beta.0", "file-loader": "^2.0.0", "fs": "^0.0.1-security", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", "node-sass": "^4.9.3", "postcss-loader": "^3.0.0", "sass-loader": "^7.1.0", "source-map-loader": "^0.2.4", "style-loader": "^0.23.0", "ts-loader": "^4.5.0", "uglifyjs-webpack-plugin": "^1.3.0", "webpack": "^4.17.1", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.6", "webpack-merge": "^4.1.4" } }
tsconfig.json:
{ "version": "2.5.3", "compilerOptions": { "jsx": "react", "module": "commonjs", "target": "es5", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, "outDir": "dist", "sourceMap": true }, "include": [ "src/**/*" ], "exclude": [ "node_modules" ] }
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
index.tsx:
import * as React from "react" import * as ReactDOM from "react-dom" ReactDOM.render( <div>Hello world</div>, document.getElementById('app') ); // console.log(1);
GetEAP.js獲取plugins:
const path = require('path');
const webpack = require('webpack');
const __DEV__ = process.env.NODE_ENV !== 'production';
/**
* extract-text-webpack-plugin外掛
* TODO: 將樣式提取到單獨的css檔案中不將css打包到js中
*/
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
/**
* html-webpak-plugin外掛,生成html外掛
* TODO: https://www.npmjs.com/package/html-webpack-plugin
*/
const HtmlWebpackPlugin = require('html-webpack-plugin');
/**
* clean-webpack-plugin外掛
* TODO: 熱更新刪除打包的檔案
*/
const CleanWebpackPlugin = require('clean-webpack-plugin');
/**
* TODO: getPlugins
*/
class getPlugins {
constructor() {
var plugins = [
new webpack.optimize.RuntimeChunkPlugin({
name: "manifest"
}),
new ExtractTextWebpackPlugin('static/css/[name].css'),
new HtmlWebpackPlugin({
favicon: path.join(__dirname, '..', 'static', 'favicon.ico'),
filename: 'index.html',
template: './src/index.html',
inject: 'body',
hash: true,
chunks: ['main', 'manifest', 'vendor'],
minify: {
removeComments: true,
collapseWhitespace: false
}
}),
new webpack.HotModuleReplacementPlugin(),
];
if (!__DEV__) {
plugins.push(new CleanWebpackPlugin('dist/', {
root: path.join(__dirname, '..'),
verbose: true,
dry: false
}));
}
return plugins;
}
}
module.exports = getPlugins;
webpack.base.config.js:
const __DEV__ = process.env.NODE_ENV !== 'production';
const path = require('path');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const GetEAP = require('../lib/GetEAP');
const config = require('../lib/config');
module.exports = {
mode: __DEV__ ? 'development' : 'production',
entry: [path.resolve(__dirname, '..', 'src', 'index.tsx')],
output: {
path: path.resolve(__dirname, '..', 'dist'),
publicPath: __DEV__ ? config.dev.assertPublicPath : config.proc.assertPublicPath,
},
module: {
rules: [{
test: /\.(css|scss)$/,
use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
// options: {
// minimize: true
// }
}, 'postcss-loader', 'sass-loader']
})
}, {
test: /\.html$/,
loader: 'html-loader?attrs=img:src img:data-src',
}, {
test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader?limit=1024&name=static/fonts/[name].[ext]'
}, {
test: /\.js$/,
use: ['babel-loader', 'source-map-loader'],
exclude: /node_modules/
}, {
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/
}]
},
plugins: new GetEAP(),
node: {
fs: 'empty'
},
};
webpack.dev.config.json:
const merge = require('webpack-merge');
const webpackBaseConfig = require('./webpack.base.config');
const path = require('path');
const config = require('../lib/config');
module.exports = merge(webpackBaseConfig, {
output: {
path: path.join(__dirname, '..', 'dist'),
publicPath: config.dev.assertPublicPath,
filename: 'static/js/[name].js',
hotUpdateChunkFilename: './static/hot/hot-update.js',
hotUpdateMainFilename: './static/hot/hot-update.json'
},
devtool: 'source-map',
resolve: {
extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.jsx']
},
});
webpack.proc.config.json:
const merge = require('webpack-merge');
const path = require('path');
const webpackBaseConfig = require('./webpack.base.config');
const config = require('../lib/config');
module.exports = merge(webpackBaseConfig, {
output: {
path: path.resolve(__dirname, '..', 'dist'),
publicPath: config.proc.assertPublicPath,
filename: 'static/js/[name].[hash].min.js',
},
});
config.js
module.exports = {
dev: {
assertPublicPath: './',
port: '8080'
},
proc: {
assertPublicPath: './',
}
};