此处将为大家介绍关于【webpack系列】从零搭建webpack4+react脚手架的详细内容,并且为您解答有关二的相关问题,此外,我们还将为您介绍关于3项目脚手架搭建npm,webpack-cli及
此处将为大家介绍关于【webpack系列】从零搭建 webpack4+react 脚手架的详细内容,并且为您解答有关二的相关问题,此外,我们还将为您介绍关于3项目脚手架搭建npm, webpack-cli及webpack、vue+webpack4 脚手架搭建、webpack 配置react脚手架(二):热更新、webpack 配置react脚手架(五):mobx的有用信息。
本文目录一览:- 【webpack系列】从零搭建 webpack4+react 脚手架(二)(webpack搭建react项目)
- 3项目脚手架搭建npm, webpack-cli及webpack
- vue+webpack4 脚手架搭建
- webpack 配置react脚手架(二):热更新
- webpack 配置react脚手架(五):mobx
【webpack系列】从零搭建 webpack4+react 脚手架(二)(webpack搭建react项目)
html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发环境?如何实现开发环境的热更新?
(1)安装html-webpack-plugin:
npm install --save-dev html-webpack-plugin
(2)在webpack.prod.conf.js中配置plugins属性。
const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); module.exports = merge(baseWebpackConfig,{ mode: ‘production‘,plugins: [ new HtmlWebpackPlugin({ template: ‘public/index.html‘,inject: ‘body‘,minify: { removeComments: true,collapseWhitespace: true,removeAttributeQuotes: true },}) ] });
(3)删除index.html中手动引入的script标签
index.html的代码应该是这样的:
<!DOCTYPE html> <html lang="en"> <head> <Meta charset="UTF-8"> <title>从零开始搭建react工程</title> </head> <body> <div id="root"></div> </body> </html>
(4)重新执行编译
npm run build
查看dist文件夹,index.html也被加载进来了,并且已经自动加上了script标签。
添加文件hash的方法很简单,只要修改 output.filename 属性即可,这里我们做一个小小的优化,把导出的文件存放在js目录下,并且直接使用name+chunkhash的方式来命名。
filename: "js/[name].[chunkhash:16].js"
其中,name就是模块名称,我们在entry中进行过配置,chunkhash是文件内容的hash,webpack默认采用md5的方式对文件进行hash。16是hash的长度,如果不设置,webpack会设置默认值为20。
现在,你的webpack.prod.conf.js文件看起来应该是这样:
const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); module.exports = merge(baseWebpackConfig,output: { filename: "js/[name].[chunkhash:16].js",},}) ] });
(1)安装clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
(2)修改webpack.prod.conf.js,使用clean-webpack-plugin
const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); const CleanWebpackPlugin = require(‘clean-webpack-plugin‘); module.exports = merge(baseWebpackConfig,}),new CleanWebpackPlugin([‘../dist‘],{ allowExternal: true }) ] });
(3)执行试试看
npm run build
编译过程,注意查看控制台输出,你会发现webpack删除了dist目录。
随着我们业务代码的增加,这个包将会越来越大。
你每次发布,这个文件都会被重新下载。你的代码有修改,用户需要重新下载无可厚非。可是,你别忘了这个app.js内还包含了很多不变的代码,比如react,react-dom。我们需要把这些不变的代码分开打包。
在webpack.base.conf.js,我们添加一个入口配置。entry有2个入口。
entry: { app: ‘./app/index.js‘,framework:[‘react‘,‘react-dom‘],
重新执行npm run build,再看看。
的确,react和react-dom 被编译成framework.js。可是,你会发现,app.js并没有减少,还是96.9KB。因为我们还缺少一步,就是抽离app.js中公共的代码。
webpack3版本是通过配置CommonsChunkPlugin插件来抽离公共的模块。webpack4版本,官方废弃了CommonsChunkPlugin,而是改用配置optimization.splitChunks的方式,更加方便。
在webpack.prod.conf.js增加如下代码:
optimization: { splitChunks: { chunks: "all",minChunks: 1,minSize: 0,cacheGroups: { framework: { test: "framework",name: "framework",enforce: true } } } }
cacheGroups对象,定义了需要被抽离的模块,其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来。name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块,虽然他们都叫framework。
重新执行npm run build你看到app.js的体积变小了 才1kb。
注意查看生成的文件的hash,接下去我们随意修改app/index.js的代码。重新执行npm run build编译。看看编译后的结果:
看到了吗,app的hash发生了改变(它不能被浏览器缓存),而framework没有改变(它会被浏览器缓存),这达到了我们预期的结果。
(1)安装uglifyjs-webpack-plugin
npm install --save-dev uglifyjs-webpack-plugin
(2)在webpack.prod.conf.js页面上引入
const UglifyJSPlugin = require(‘uglifyjs-webpack-plugin‘);
(3)optimization内配置minimizer参数
minimizer: [ new UglifyJSPlugin() ],
你的optimization参数现在应该是这样:
optimization: { minimizer: [ new UglifyJSPlugin() ],splitChunks: { chunks: "all",cacheGroups: { framework: { priority: 200,test: "framework",enforce: true,reuseExistingChunk: true },vendor: { priority: 10,test: /node_modules/,name: "vendor",reuseExistingChunk: true } } } }
(4)重新执行npm run build
npm run build
webpack-dev-server这个模块提供了开发服务的支持,通过在webpack.dev.conf.js文件配置devServer可以方便地整合webpack-dev-server。
(1)安装webpack-dev-server
npm install --save-dev webpack-dev-server
(2)在build中添加webpack.dev.conf.js文件
const path = require(‘path‘); const merge = require(‘webpack-merge‘); const baseWebpackConfig = require(‘./webpack.base.conf.js‘); const HtmlWebpackPlugin = require(‘html-webpack-plugin‘); const webpack = require(‘webpack‘); module.exports = merge(baseWebpackConfig,{ mode: ‘development‘,output: { filename: "js/[name].[hash:16].js",minify: { html5: true },hash: false }),new webpack.HotModuleReplacementPlugin() ],devServer: { port: ‘8080‘,contentBase: path.join(__dirname,‘../public‘),compress: true,historyApiFallback: true,hot: true,https: false,noInfo: true,open: true,proxy: {} } });
HotModuleReplacementPlugin是webpack热更新的插件,设置devServer.hot为true,并且在plugins中引入HotModuleReplacementPlugin插件即可。
还需要注意的是我们开启了hot,那么导出不能使用chunkhash,需要替换为hash。
(3)在package.json增加一个npm scripts
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
(4)执行dev命令
npm run dev
打开 http://localhost:8080 查看,你可以尝试改动index.js的代码,浏览器自动更新了,说明整合webpack-dev-server成功。 你可能注意到,对于css相关的技术栈,我只字未提,别急,下一节我们会详细针对css相关的技术栈进行整合。
3项目脚手架搭建npm, webpack-cli及webpack
1.所有需要使用NPM 的项目都需要使用npm init进行初始化
webpack.github.io/docs/configuration.html
使用npm install进行安装的话,会在根目录下产生一个node_modules的文件夹,
所有你npm 的包都会放置于此
-g全局安装
--registry= 指向安装,可以把安装引导到国内环境的安装
2.webpack模块化文件
安装 npm install webpack@1.15.0 --save-dev可以初始化项目中的安装
版本
2.操作
cnpm install webpack@1.15.0 --save-dev
webpack在使用包的时候先使用本地的包,没有的时候才选择使用全局的安装包
webpack使用1.15.0而不使用2.0是因为其中有default的关键字和ie8以下的浏览器有冲突导致出现错误。
--save-dev可以把项目的配置记录在package.json中-包括版本
3.webpack.config.js
3.loader
4.常用命令工具
webpack 常用于调试代码用
wepack -p只用于做线上打包时,会把所有文件都做最小话压缩
webpack --watch 用作监听文件的改变,和自动编译,一般用于开发过程
webpack --config webpack.config.js 改变默认的配置文件位置
删除 rm -r -f node_modules
5.webpack-dev-server
作用:前端开发的服务器
webpack --watch不能刷新浏览器基本不用
3-4npm和webpack的初始化
- npm init 设置各种文件配置
- sudo npm install webpack -g 全局的webpack安装
-
npm install webpack@1.15.0 --save-dev 项目目录安装webpack
查看版本webpack -v 是否安装成功
某些情况无法查看的情况需要 npm install webpack-cli -g
4.文件的建立
app.js
cats = require(''./cats.js'');
console.log(cats);
cats.js
var cats = [''dave'', ''henry'', ''martha''];
module.exports = cats;
5.打包文件的建立
注意webpack的版本可能会导致打包失败,而版本的额设置需要同步的在package.json中设置好,
然后npm init,再重新安装webpack
webpack ./src/page/index/index.js ./dist/app.js
把index.js打包进app.js中去
较为麻烦
直接把打包文件设置好进行
webpack.config.js
const path = require(''path'');
module.exports = {
entry: ''./src/page/index/index.js'',
output: {
path: path.resolve(__dirname, ''./dist''),
filename: ''app.bundle.js''
}
};
webpack -p进行打包
6.webpack对脚本的处理
1)jquery的使用
npm install jquery --save
然后在index中设置好
以上安装方法无法在全局中使用
卸载后重新安装,某些情况下无法供全局使用 npm uninstall jquery --save
- 直接在index.html中引入,就成了全局的jq了
然后在index.js设置
删除掉jqury npm uninstall jquery --save
2.js多入口的问题 entry
module.exports = {
entry: {
''index'':[''./src/page/index/index.js''],
''login'':[''./src/page/login/index.js''],
},
output: {
path: path.resolve(__dirname, ''./dist''),
filename: ''js/[name].js''
}
};
3.模块化引入jQuery
index.js
var $$ = require(''jquery'');
$$(''body'').html("HELLO JQ*****");
webpack.config.js
externals:{
''jquery'':''window.$''
}
此处注意一下两个文件的先后顺序
4.使用CommonsChunkPlugin提取公共代码
特别注意webpack 4已经更改了该插件的支持
关于版本的问题
***1.安装 在全局下安装:npm install webpack -g
安装指定版本:npm install web
pack@<version> -g 例如:npm install webpack@3.4.1 -g
如果只是用来练习全局安装就可以了,一开始装了个4.8.3版本的,node也是最新的npm也好着,一做项目就出现错误,4.*.*版本以上还需要安装另外一个东西,具体的可去webpack官网看。
最后只能把webpack删除,重新装了一个指定版本的,才没有什么问题了。
***2.删除 在全局下删除 npm uninstall webpack -g
最好将项目目录下的node-modules一起删除,否则会有残留文件影响下一次的结果。
特别注意在安装全局的webpack和项目的webpack时注意版本的一致性3.6.0
webpack-cli的版本不能比webpack的版本高,不然会出现问题
5.将不同的公共代码打进同一个文件中
webpack.config.js打包入口文件
./src/page/common/index.js''和 ''index'':[''./src/page/index/index.js''],打包进base.js文件中、
entry: {
''common'':[''./src/page/common/index.js''],
''index'':[''./src/page/index/index.js''],
''login'':[''./src/page/login/index.js'']
},
脚本
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "common",
filename: "js/base.js"
})
]
原理-先定义一个公共的module.js》common/index.js 引入require(''../module.js'');》打包
vue+webpack4 脚手架搭建
1, vue 中 h => h(App) 的含义:
//render: h => h(App) 是下面内容的缩写:
render: function (createElement) {
return createElement(App);
}
//进一步缩写为(ES6 语法):
render (createElement) {
return createElement(App);
}
//再进一步缩写为:
render (h){
return h(App);
}
//按照 ES6 箭头函数的写法,就得到了:
render: h => h(App);
2 文章中 vue 组件中如果引入了样式,一定要引入css
{
test:/\.css$/,
use:[
''style-loader'',
''css-loader''
]
}
----
参考文章:
1: 从零开始配置 webpack4 + vue2.x (一)
2: 从零开始的 webpack4 + vue2.x
webpack 配置react脚手架(二):热更新
下面继续配置 webpack dev server hot module replacement:
首先配置dev-server 安装 npm i webpack-dev-server -D
const isDev = process.env.NODE_ENV === ''development''
const config = {
entry:{},
output:{},
plugins:{}
}
if(isDev){
config.devServer = {
host: ''0.0.0.0'', //设置 0.0.0.0 的host 可以访问 localhost,127.0.0.1,本季ip来访问
contentBase: path.join(__dirname, ''../dist''), //因为,devserver是服务打包后的文件,所以和output的path 保持一致即可
port: ''8888'',
hot: true,
overlay: {
errors: true //server有任何的错误,则在网页中 蒙层加提示
}
}
}
module.exports = config;
修改json文件: "dev:client": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.client.js",
其中 cross-env 是兼容了win mac linux的NODE_ENV,也是一个安装包: npm i cross-env -D
然后 npm run dev:cient 即可以启动服务 localhost:8888;
发现 app.js是无法获取到的,其路径为: http://localhost:8888/public/app.js 可以看出是多了一层 public;
根据server的配置项:contentBase 是把dev-server放在了dist目录下,开启的服务器。则 locahost:8888 相当于 dist目录,而之前output配置的输出文件前面是有路径 public的,所以 dev-server也需要增加这个配置:
if(isDev){
config.devServer = {
host: ''0.0.0.0'', //设置 0.0.0.0 的host 可以访问 localhost,127.0.0.1,本季ip来访问
contentBase: path.join(__dirname, ''../dist''), //因为,devserver是服务打包后的文件,所以和output的path 保持一致即可
port: ''8888'',
hot: true,
overlay: {
errors: true //server有任何的错误,则在网页中 蒙层加提示
},
publicPath: ''/public/'', //增加公共路径,对应着output的 publicPath
historyApiFallback: {
index: ''/public/index.html'' //这里是给本地服务器增加功能:因为是单页面应用,如果刷新页面,或者访问不到路由,则跳转到首页
},
}
}
注意:一定要把打包生成的dist目录删除掉,在执行 npm run dev:client 这时因为,服务器会先检测本地磁盘是否有dist目录,如果有就会调取这里面的文件!!
===================华丽的分割线
接下来配置 热更新 hot,
Q:webpack-dev-server 已经是热加载,为何还要在 react 项目还要安装 react-hot-loader 呢?
A:其实这两者的更新是有区别的,webpack-dev-server 的热加载是开发人员修改了代码,代码经过打包,重新刷新了整个页面。而 react-hot-loader 不会刷新整个页面,它只替换了修改的代码,做到了页面的局部刷新。但它需要依赖 webpack 的 HotModuleReplacement 热加载插件 (参考文章: react使用react-hot-loader实现局部热更新)
首先在 .babelrc 文件中增加 对react hot更新的配置:
{
"presets": [
["es2015", { "loose": true }],
"react"
],
"plugins": [ "react-hot-loader/babel"] //使用babel的情况下,添加 react-hot-loader,支持react 热更新
}
安装包: npm i react-loader@next -D //教程中这里是最新的版本,尚未正式版,开发的时候注意版本
修改app.js 入口文件:
import React from ''react''
import ReactDOM from ''react-dom''
import App from ''./App.jsx''
ReactDOM.hydrate(<App />,document.getElementById(''root''));
if (module.hot) {
module.hot.accept(''./App.jsx'', () => {
const NextApp = require(''./App.jsx'').default
ReactDOM.hydrate(<NextApp />,document.getElementById(''root''))
})
}
// module.hot 监听到 app.jsx发生变化之后,重新获取 app.jsx 为NextApp 然后重新渲染;
修改package.js文件:
const webpack = require(''webpack''); //因为用到了webpack下的包 HotModuleReplacementPlugin
const config ={
}
if(isDev){
config.entry=[
''react-hot-loader/patch'', //入口文件中要把 hot 打包进去
path.join(__dirname,''../client/app.js'')
],
config.devServer = {
host: ''0.0.0.0'',
contentBase: path.join(__dirname, ''../dist''),
port: ''8888'',
hot: true, //打开这里
overlay: {
errors: true
},
publicPath: ''/public/'',
historyApiFallback: {
index: ''/public/index.html''
}
}
config.plugins.push(new webpack.HotModuleReplacementPlugin) //增加了这里
}
最后还要返回来在 app.js 入口文件中配置:
import React from ''react''
import ReactDOM from ''react-dom''
import { AppContainer } from ''react-hot-loader''
import App from ''./App.jsx''
ReactDOM.hydrate(<App />,document.getElementById(''root''));
const root = document.getElementById(''root'');
const render = Component => {
ReactDOM.hydrate(
<AppContainer>
<Component/>
</AppContainer>,
root
)
}
render(App);
if (module.hot) {
module.hot.accept(''./App.jsx'', () => {
const NextApp = require(''./App.jsx'').default
render(NextApp);
})
}
这样才能热更新!
=================================服务端更新配置
上面书写了客户端的热更新,并且热更新的文件都存在内存中,所以服务端不能再从 dist文件夹下获取依赖的 js和 html文件,因此,服务端的js文件也需要区分是否是dev模式:
const express = require(''express'')
const ReactSSR = require(''react-dom/server'');
const fs = require(''fs'')
const path = require(''path'')
const app = express();
const isDev = process.env.NODE_ENV === ''development''; //在这里定义
if(!isDev){
const serverEntry = require(''../dist/server-entry'').default;//引入的是服务端的配置打包后的js文件
const template = fs.readFileSync(path.join(__dirname, ''../dist/index.html''), ''utf8'')//同步引入客户端打包生成的 html 文件,如果不使用 utf8 则是buffer文件
app.use(''/public'', express.static(path.join(__dirname, ''../dist''))); //给静态文件指定返回内容,这里给piblic文件夹下的内容返回的是静态文件的dist文件夹
app.get(''*'', function (req, res) {
const appString = ReactSSR.renderToString(serverEntry);
res.send(template.replace(''<!--app-->'',appString)) //用返回的js文件替换掉模板中的<app>,然后发送的是模板文件
})
}else{
//util 文件夹下的 dev.static.js
const devStatic = require(''./util/dev.static.js'');
devStatic(app); //之所以这里把 app 传递进去,是因为app是 express(),我们可以在新建的文件中继续使用 app.get、app.send 等函数
}
app.listen(3333, function () {
console.log(''server is listening on 3333'')
})
根据以上代码可知,把原来的从dist目录下获取文件的代码放在了 不是 dev模式下了,而dev模式下我们放在了 util/dev.static.js 文件下。
根据if else可以看出,在文件 dev.static.js 文件中我们要做的事情是:把静态文件js和模版从内存中提取出来,交给app.get请求 然后 send 出去。
接下来编辑 dev.static.js 文件,首先安装 npm i axios -S
步骤一: 获取内存中的模板html文件
const axios = require(''axios'');// 在浏览器端和服务器端都可以使用 axios
/*在这里从内存中获取模版html,因为每次dev-server启动的是本地的服务,url是固定的;
这样可以根据 dev-server 实时的拿到最新的 模板文件
*/
const getTemplate = () => {
return new Promise((resolve,reject)=>{
axios.get(''http://localhost:8888/public/index.html'')
.then(res => {
resolve(res.data); //返回的内容放在了 data中
})
.catch(reject)
})
}
module.exports = function (app) {
app.get("*",function(req,res){
})
}
步骤二:获取。server-entry.js等bundle文件
const axios = require(''axios'');
//从内存中获取 js等bundle文件,启动webpack,通过webpack打包的结果,获取bundle文件。
const webpack = require(''webpack'');
//通过 config.server.js 文件 获取 输出文件路径等信息
const serverConfig = require(''../../build/webpack.config.server.js'');
const getTemplate = () => {
return new Promise((resolve,reject)=>{
axios.get(''http://localhost:8888/public/index.html'')
.then(res => {
resolve(res.data);
})
.catch(reject)
})
}
// 通过webpack的watch方法,监听配置文件中的 entry 入口文件(及其依赖的文件)是否发生变化,一旦变化,就会重新打包(类似于热更新)
const serverCompiler = webpack(serverConfig);
serverCompiler.watch({},(err,status)=>{//status 在终端上显示的信息
if(err) throw;
let stats = status.toJson();
stats.error.forEach(err => console.log(err));
stats.waring.forEach(warn => console.warn(warn));
const bundlePath = path.join(
serverConfig.output.path,
serverConfig.output.filename
);// 获取输出文件的路径
})
module.exports = function (app) {
app.get("*",function(req,res){
})
}
获取到 生成的 文件名字之后需要在 内存中读取 文件:
要使用 memory-fs,所以要安装 npm i memory-fs -D;
const axios = require(''axios'');
const path = require(''path'');
const webpack = require(''webpack'');
const serverConfig = require(''../../build/webpack.config.server.js'');
// 要使用 memory-fs,所以要安装 npm i memory-fs -D;
// 在内存中读写文件,这样就可以从内存中读取 获取到的文件
const MemoryFs = require(''memory-fs'');
//最后要把得到的js文件,渲染到dom上去,所以要用到
const ReactDomServer = require(''react-dom/server'');
const getTemplate = () => {
return new Promise((resolve,reject)=>{
axios.get(''http://localhost:8888/public/index.html'')
.then(res => {
resolve(res.data);
})
.catch(reject)
})
}
//通过module的 constructor 构造方法去创建一个新的 module
const Module = module.constructior
let serverBundle;
const mfs = new MemoryFs;//new 一个 对象;
const serverCompiler = webpack(serverConfig);
serverCompiler.outputFileSystem = mfs; //webpack 提供的配置项,其输出通过mfs内存读写,这里如果写错名字就会写到硬盘中
serverCompiler.watch({},(err,status)=>{
if(err) throw;
let stats = status.toJson();
stats.error.forEach(err => console.log(err));
stats.waring.forEach(warn => console.warn(warn));
const bundlePath = path.join(
serverConfig.output.path,
serverConfig.output.filename
);// 获取输出文件的路径
//通过 mfs 读取文件的路径,就可以得到文件,是 string 类型的文件,无法直接使用
const bundle = mfs.readFileSync(bundlePath,''utf-8''); //需要传入 编码格式
const m = new Module();
//动态编译成一个文件,需要给这个文件指定文件名字,否则无法在缓存中进行缓存,下次则拿不到该文件
m._compile(bundle,''server-entry.js'');//使用module的_compile方法将String的文件,生成一个新的 模块,转换成了真正可以读取的文件
/*为了在后面的 app.get方法中使用。将生成的文件赋值给全局变量;
此外,因为是在 watch中执行的,每次依赖的文件更新,输出的文件也会更新*/
serverBundle = m.exports.default;
})
module.exports = function (app) {
app.get("*",function(req,res){
getTemplate().then(template => {
const content = ReactDomServer.renderToString(serverBundle);
res.send(template.replace(''<!--app-->'',content))
})
})
}
最后在package.json 中定义命令:
{
"script":{
"dev:server":"cross-env NODE_ENV = development node server/sever.js"
}
}
启动客户端和服务器端:npm run dev:client npm run dev:server;
发现无论是js还是html都返回的一样,所以就想之前 对静态文件的 public中做的区分,但是由于这个是在内存中,所以不同:
安装: npm i http-proxy-middleware -D 做代理的中间件
const axios = require(''axios'');
const path = require(''path'');
const webpack = require(''webpack'');
const serverConfig = require(''../../build/webpack.config.server.js'');
const MemoryFs = require(''memory-fs'');
const ReactDomServer = require(''react-dom/server'');
//引入中间件
const proxy = require(''http-proxy-middleware'');
const getTemplate = () => {
return new Promise((resolve,reject)=>{
axios.get(''http://localhost:8888/public/index.html'')
.then(res => {
resolve(res.data);
})
.catch(reject)
})
}
const Module = module.constructior
let serverBundle;
const mfs = new MemoryFs;
const serverCompiler = webpack(serverConfig);
serverCompiler.outputFileSystem = mfs;
serverCompiler.watch({},(err,status)=>{
if(err) throw;
let stats = status.toJson();
stats.error.forEach(err => console.log(err));
stats.waring.forEach(warn => console.warn(warn));
const bundlePath = path.join(
serverConfig.output.path,
serverConfig.output.filename
);
const bundle = mfs.readFileSync(bundlePath,''utf-8'');
const m = new Module();
m._compile(bundle,''server-entry.js'');
serverBundle = m.exports.default;
})
module.exports = function (app) {
//服务器端端口是 3333;客户端的端口是 8888;
//这里做的代理是,访问当前3333端口的public文件时,代理去请求客户端的 8888端口文件
app.use(''/public'',proxy({
target:''http://localhost:8888''
}))
app.get("*",function(req,res){
getTemplate().then(template => {
const content = ReactDomServer.renderToString(serverBundle);
res.send(template.replace(''<!--app-->'',content))
})
})
}
webpack 配置react脚手架(五):mobx
1. 配置项。使用mobx,因为语法时es6-next,所以先配置 .babelrc 文件
{ "presets": [ ["es2015",{ "loose": true }],"stage-1",//改动了这里 "react" ],"plugins": ["transform-decorators-legacy","react-hot-loader/babel"] //还有这里,transform-decorators-legacy 放在 数组的第一项 }
安装:
npm i transform-decorators-legacy babel-preset-stage-1 -D
npm i mobx-react -S
2. 使用 在store/app-state.js中:
import { observable,computed,autorun,action,} from ‘mobx‘ class AppState { @observable count = 0; @observable name = ‘jok‘ @computed get msg() { return `${this.name} say count is ${this.count}` } @action.add(){ this.count + =1; } } const appState = new AppState(); autorun(()=>{ console.log(appState.msg); }) setInterval(()=>{ appState.add(); }) export default appState;
调用方法:
关于【webpack系列】从零搭建 webpack4+react 脚手架和二的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于3项目脚手架搭建npm, webpack-cli及webpack、vue+webpack4 脚手架搭建、webpack 配置react脚手架(二):热更新、webpack 配置react脚手架(五):mobx的相关知识,请在本站寻找。
本文标签: