注:以下Settings后面不一定就有那个目录,这里的意思是打开Settings后搜索这个即可
File/Settings/Languages & Frameworks/JavaScript里选择React JSX
File/Settings/Directories,里面可以设置和查看项目里哪里目录被exclude,哪些目录被作为根目录,一般来说dist(即最后打包后的目录)目录,node_modules目录等等我们是要exclude的
其他webstorm配置:
-
File/Settings/Debugger可以更改通过webstorm打开浏览器的端口号
-
解决
unresolved function method 'require'
,可以在File/Settings/Language & Frameworks/JavaScript/Libraries中添加node.js Core
npm init
打开terminal,运行webpack命令,成功后会在dist目录下生成bundle.js文件,然后再根目录创建一个index.html如下:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="build/bundle.js">
</script>
</body>
</html>
然后点击右上角,在浏览器中运行,即可验证打包结果
npm install babel-core babel-loader babel-preset-es2015 babel-preset-react --save-dev
然后在根目录下建立.babelrc文件,在里面写入
{
"presets": ["es2015", "stage-3", "react"]
}
在webpack.config里面的module.export的module里加上:
loaders: [{
test: /\.js$/, // 匹配.js文件,如果通过则使用下面的loader
exclude: /node_modules/, // 排除node_modules文件夹
loader: 'babel' // 使用babel(babel-loader的简写)作为loader
}]
4.1 webpack和webpack-dev-server:
安装方式:
npm install webpack --save-dev
npm install webpack-dev-server --save-dev
4.1.1 Webpack作为模块打包工具,提供两种用户交互接口:
- Webpack CLI tool:默认的交互方式(已随Webpack本身安装到本地)
- webpack-dev-server:一个Node.js服务器(需要开发者从npm自行安装)
WebpackCLI(有利于生产模式下打包),这种方式可以从命令行获取参数也可以从配置文件(默认叫webpack.config.js)获取,将获取到的参数传入Webpack来打包。
用法:
1.当在终端执行webpack的时候(全局或者是非全局安装没有影响,只要能执行webpack命令),也就是使用webpack.config.js生成了打包后的bundle.js
2.非全局安装,即npm install webpack --save
,然后在package.json
中加入:
"scripts": {
// 通过运行npm run build 来编译生成生产模式下的bundles
"build": "webpack --config webpack.config.prod.js -p"
}
然后通过npm run build
生成bundle.js
4.1.2 webpack-dev-server(有利于在开发模式下编译)
这是一个基于Express.js框架开发的web server,默认监听8080端口。server内部调用Webpack,这样做的好处是提供了额外的功能如热更新“Live Reload”以及热替换“Hot Module Replacement”(即HMR)。
用法:
方式 1:
// 全局安装
npm install webpack-dev-server --save
// 终端输入
$ webpack-dev-server --inline --hot
用法 2:
// 添加到package.json scripts
"scripts": {
"start": "webpack-dev-server --inline --hot" // 相当于把npm的start命令指向webpack命令
// 上面这一步的参数也可以通过在webpack.config.js设置devServer,但是注意不要同时使用这两种方式
// 通过运行npm run dev(需要在package.json中的scripts中添加`" dev " : " webpack-dev-server --devtool eval --progress --colors --content-base build " `)来生成开发模式下的bundles以及启动本地server
devServer: {
inline: true,
hot:true,
port: 8080(默认),
colors: true(默认) // 使终端输出的文件为彩色的
}
}
// 运行:
$ npm start
// 浏览器预览:
http://localhost:8080
“inline”选项会为入口页面添加“热加载”功能,“hot”选项则开启“热替换(Hot Module Reloading)”,即尝试重新加载组件改变的部分(而不是重新加载整个页面)。如果两个参数都传入,当资源改变时,webpack-dev-server将会先尝试HRM(即热替换),如果失败则重新加载整个入口页面。
// 当资源发生改变,以下三种方式都会生成新的bundle,但是又有区别:
// 1. webpack-dev-server 不会刷新浏览器
// 2. webpack-dev-server --inline 刷新浏览器
// 3. webpack-dev-server --inline --hot 重新加载改变的部分,如果失败,则刷新页面
4.2 entry相关配置
在配置之前,我们首先要在根目录下建立一个webpack.config.js文件,用于配置我们的webpack,建立后写入:
var webpack=require('webpack');
来引入webpack
entry支持字符串,数组,对象三种形式
如果你的应用只有一个单一的入口,entry值你可以使用任意类型,最终输出的结果都是一样的
如'src/index.js'
,['src/index.js']
,{index: 'src/index.js'}
-
entry是数组:启动时加载数组中所有的模块,导出的是最后一个
-
entry是对象(即用于多页面应用):将会创建多个bundle.js,也就是生成每个index.html的bundle.js,对象中的key为chunk名:
官方示例:
entry: {
page1: "./page1",
page2: ["./entry1", "./entry2"]
},
output: {
// Make sure to use [name] or [id] in output.filename
// when using multiple entry points
filename: "[name].bundle.js",
chunkFilename: "[id].bundle.js"
}
例1:
entry: {
index1: '/src/main1.js',
index2: '/src/main2.js'
},
output: {
path: "/dist"
filename: "[name].bundle.js" // index1.js, index2.js
}
有的配置可能会有__dirname
这个变量,这个变量表示执行脚本(这里即是webpack.config.js)所在的目录`
4.3 output相关配置
在开发模式下的静态资源是以相对路径的形式引入到页面中,然而在生产环境中,他们可能位于不同的服务器或者CDN上,这就需要一种机制,自动实现这前者到后者的转换
path和publicPath就是实现这个转换的关键:
4.4 各种loader安装及配置
npm install less-loader css-loader style-loader url-loader file-loader postcss-loader autoprefixer --save-dev
多个loader可以用在同一个文件上并且被链式调用。链式调用时从右到左执行且loader之间用“!”来分割,例如,假设我们有一个名为“myCssFile.css”的css文件,然后我们想将它的内容使用style标签内联到最终输出的html里边。我们可以使用css-loader和style-loader两个loader来达到目的。
loaders:[
{
test:/\.css$/,
loader:'style-loader!css-loader!postcss-loader'
},
{
test:/\.jsx?$/,
loader:'babel',
exclude: /node_modules/,
query:{
presets:['es2015','react']
}
},
{
test:/\.(png|jpg)$/,
loader:'url-loader?limit=8192'
},
{
test:/\.less$/,
loader:'style-loader!css-loader!less-loader'
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader?limit=10000&mimetype=application/font-woff"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader"
}
],
postcss: [
require('autoprefixer')//调用autoprefixer插件
],
-
query:代表执行loader时对loader的一些配置,如我们可以配置url-loader来将小于1024字节的图片使用DataUrl替换而大于1024字节的图片使用url,我们可以用如下两种方式通过传入“limit“参数来实现这一目的:
-
test:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
上面的
{
test:/\.jsx?$/,
loader:'babel',
exclude: /node_modules/,
query:{
presets:['es2015','react']
}
}
其实在实际中并不会这么配置,因为在很多项目里babal的配置可能比较大,因此你可以把babal-loader的配置项单独保存在一个名为”.babelrc“的文件中,在执行时babal-loader将会自动加载.babelrc文件,如:
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel'
}
]
}
//.bablerc
{
presets: ['react', 'es2015']
}
4.5 rosolve相关配置
rosolve就是自动识别文件后缀,这样import写的时候不用写后缀,方便一点
resolve: {
extensions: ['', '.js', '.jsx', '.scss', '.json']
}
4.6 source-map相关配置
打包后的bundle.js在调试的时候是不方便的,我们需要将它的某一个位置与打包前的js文件一一对应,因此我们需要配置Source Maps:
devtool: 'source-map',//配置生成Source Maps,选择合适的选项
除此之外,还有cheap-module-source-map,eval-source-map,cheap-module-eval-source-map等等
4.7 插件相关配置 插件一般是针对各种loader或者最后的bundle.js而言
- UglifyJsPlugin:用于压缩js文件:
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
- HtmlWebpackPlugin:依据一个简单的模板,生成最终的Html5文件
webpack.config.js顶部加入:
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
})
],
- HotModuleReplacementPlugin:
plugins: [
new webpack.HotModuleReplacementPlugin() //热加载插件
],
4.8 版本号配置:
module.exports = {
output: {
filename: "[name]-[chunkhash].js",
chunkFilename: "bundle-[chunkhash].js"
},
plugins: [
new ExtractTextPlugin("[name]-[contenthash].css")
],
}
其中js用的是webpack的chunkhash,而css用的是contenthash,contenthash是根据内容生成的hash。如果不用contenthash,那么一改js,css的版本号也会跟着改变,这个就有问题了。webpack还有另外一个自带的叫做”[hash]”,这个hash是所有文件都用的同一个哈希,也就是说某个文件改了,所有文件的版本号都会跟着改,所以一般不用这个。
生成版本号后,那么需要自动修改原来的url,这样才不会资源导致404:
npm install react react-dom --save-dev
5.1 安装react-transform-hmr
首先需要知道webpack-dev-server自己的--hot模式只能即时刷新页面,但状态保存不住。因为React有一些自己语法(JSX)是HotModuleReplacementPlugin搞不定的。
而react-hot-loader是在--hot基础上做了额外的处理,来保证状态可以存下来。不过现在好像使用不太多了,现在使用的是下面这种方式:
HMR是一个webpack插件,它让你能浏览器中实时观察模块修改后的效果,但是如果你想让它工作,需要对模块进行额外的配置; Babel有一个叫做react-transform-hrm的插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作;
npm install --save-dev babel-plugin-react-transform react-transform-hmr
然后在.babelrc中加入:
"env": {
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}]
}]]
}
}
5.2 Developer Tools安装与配置
使用chrome的react和redux插件可以更好的方便调试,如果不喜欢,也可以用下面的方式代替
npm i --save-dev redux-devtools redux-devtools-log-monitor redux-devtools-dock-monitor
然后参考手册
"start:dev": "webpack-dev-server --inline --content-base public --history-api-fallback",
we could use the WebpackDevServer API in a JavaScript file instead of the CLI in an npm script and then turn this path into config shared across all of these files.