前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >webpack配置React开发环境(上)

webpack配置React开发环境(上)

作者头像
牧云云
发布2018-05-02 11:25:56
1.6K0
发布2018-05-02 11:25:56
举报
文章被收录于专栏:云瓣

Webpack 是一个前端资源加载/打包工具,我们部门的一条主要技术栈就是Webpack+React+ES6+node,虽然之前自己做个人项目也接触好多次Webpack,但是自己并没有研读总结过Webpack的知识点,读了wepack-demos,这些demos虽然是基于webpack@1.x的,但是举例得蛮简洁明了,所以这次就简单翻译此文的一些重点。

什么是Webpack?

Webpack是一个前端资源加载/打包工具,只需要相对简单的配置就可以提供前端工程化需要的各种功能,并且如果有需要它还可以被整合到其他比如 Grunt / Gulp 的工作流。

安装 Webpack:npm install -g webpack。

Webpack 使用一个名为 webpack.config.js 的配置文件。

代码语言:javascript
复制
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

一些你应该知道的命令:

  • webpack —— 进行一次编译
  • webpack -p —— 进行一次编译(压缩成一行)
  • webpack --watch —— 持续编译
  • webpack -d  —— 编译完成后包含一个maps文件
  • wepack --colors —— 使压缩文件变漂亮(我暂时没看出来)

在开发应用程序时,可以在package.json文件中编写scripts字段,如下所示:

代码语言:javascript
复制
// package.json
{
  // ...
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "deploy": "NODE_ENV=production webpack -p"
  },
  // ...
}
入口文件

入口文件是一个Webpack将会读取它并将它编译成bundle.js的文件

demo01:单个入口文件:

代码语言:javascript
复制
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

demo02:多个入口文件:(它对多页面app是非常有用的)

代码语言:javascript
复制
// index.html
<html>
  <body>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

// webpack.config.js
module.exports = {
  entry: {
    bundle1: './main1.js',
    bundle2: './main2.js'
  },
  output: {
    filename: '[name].js'
  }
};
Babel-loader

加载器是预处理器,它转换您的应用程序的资源文件(更多信息)。例如,Babel-loader可以将JSX / ES6文件转换为JS文件。官方文档有一个完整的加载器列表

代码语言:javascript
复制
// webpack.config.js
module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
    ]
  }

或者
module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['es2015', 'react']
      }
    }
  ]
}
CSS-loader

Webpack允许您在JS文件中引用CSS,然后使用CSS-loader预处理CSS文件。

代码语言:javascript
复制
// main.js
require('./app.css');
代码语言:javascript
复制
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.css$/, loader: 'style-loader!css-loader' },
    ]
  }
};

注意,你必须使用两个加载器来转换CSS文件。首先是CSS-loader读取CSS文件,另一个是Style-loader将Style标签插入HTML页面。不同的装载器通过感叹号(!)链接。

启动服务器后,index.html将具有内部样式表。(demo04)

Image loader
代码语言:javascript
复制
// main.js
var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);

var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

// index.html
<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
    ]
  }
};

url-loader转换图像文件。如果图像大小小于8192字节,则将其转换为数据URL;否则,它将被转换为正常的URL。如你所见,问号(?)用于将参数传递到加载器。

启动服务器后,small.png和big.png将有以下URL。

代码语言:javascript
复制
<img src="data:image/png;base64,iVBOR...uQmCC">
<img src="4853ca667a2b8b8844eb2693ac1b2578.png">
UglifyJS Plugin(减少输出)

Webpack有一个插件系统来扩展其功能。例如,UglifyJs Plugin将缩小输出(bundle.js)JS代码。(demo07)

代码语言:javascript
复制
// webpack.config.js
var webpack = require('webpack');
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new uglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

压缩的效果如下:

代码语言:javascript
复制
// 压缩前
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('<h1>' + longVariableName + '</h1>');

// 压缩后
var o="Hello";o+=" World",document.write("<h1>"+o+"</h1>")
自动打开浏览器&&自动创建index.html

此演示向您演示如何加载第三方插件。 html-webpack-plugin可以为您创建index.html,并且当Webpack加载时,open-browser-webpack-plugin可以打开一个新的浏览器选项卡。

代码语言:javascript
复制
// main.js
document.write('<h1>Hello World</h1>');

// webpack.config.js
var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Webpack-demos',
      filename: 'index.html'
    }),
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    })
  ]
};
环境标志

您可以仅在具有环境标志的开发环境中启用一些代码(demo09)

代码语言:javascript
复制
// main.js
document.write('<h1>Hello World</h1>');

if (__DEV__) {
  document.write(new Date());
}

// index.html
<html>
<body>
  <script src="bundle.js"></script>
</body>
</html>

// webpack.config.js
var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [devFlagPlugin]
};

然后现在将环境变量传递到webpack。

代码语言:javascript
复制
# Linux & Mac
$ env DEBUG=true webpack-dev-server

# Windows
$ set DEBUG=true
$ webpack-dev-server
Common chunk(抽出公用脚本)

当多脚本具有公共块时,可以使用CommonsChunkPlugin将公共部分提取到单独的文件中。

代码语言:javascript
复制
// main1.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello World</h1>,
  document.getElementById('a')
);

// main2.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h2>Hello Webpack</h2>,
  document.getElementById('b')
);

// index.html
<html>
  <body>
    <div id="a"></div>
    <div id="b"></div>
    <script src="init.js"></script>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

// webpack.config.js
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
  entry: {
    bundle1: './main1.jsx',
    bundle2: './main2.jsx'
  },
  output: {
    filename: '[name].js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
    ]
  },
  plugins: [
    new CommonsChunkPlugin('init.js')
  ]
}
Vendor chunk

您还可以使用CommonsChunkPlugin从脚本中将供应商库提取到单独的文件中。(优化代码层面)

代码语言:javascript
复制
// main.js
var $ = require('jquery');
$('h1').text('Hello World');

// index.html
<html>
  <body>
    <h1></h1>
    <script src="vendor.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

// webpack.config.js
var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js',
    vendor: ['jquery'],
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js')
  ]
};

如果你想要一个模块作为变量在每个模块,如使$和jQuery可用在每个模块没有写require(“jquery”)。你应该使用ProvidePlugin(官方文档)。

代码语言:javascript
复制
// main.js
$('h1').text('Hello World');


// webpack.config.js
var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js'
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
};
热更新

热模块替换(HMR)交换,添加或删除模块,而应用程序正在运行,而没有页面重新加载。

您有两种方法通过webpack-dev-server启用热模块更换。

(1)在命令行中指定--hot和--inline

代码语言:javascript
复制
$ webpack-dev-server --hot --inline

选项的含义:

  • --hot: 添加HotModuleReplacementPlugin并将服务器切换到热模式。
  • --inline: 将webpack-dev-server运行时嵌入到bundle中。
  • --hot --inline: 还添加了webpack/hot/dev-server条目。

(2)修改webpack.config.js文件(demo15)

  • 添加新webpack.HotModuleReplacementPlugin() 的插件
  • 添加webpack/hot/dev-server 和 webpack-dev-server/client?http://localhost:8080 到输入字段
代码语言:javascript
复制
// webpack.config.js
var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: [
    'webpack/hot/dev-server',
    'webpack-dev-server/client?http://localhost:8080',
    './index.js'
  ],
  output: {
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015', 'react']
      },
      include: path.join(__dirname, '.')
    }]
  }
};
代码语言:javascript
复制
// App.js
import React, { Component } from 'react';

export default class App extends Component {
  render() {
    return (
      <h1>Hello World</h1>
    );
  }
}

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

// index.html
<html>
  <body>
    <div id='root'></div>
    <script src="/static/bundle.js"></script>
  </body>
</html>
有用的链接

 下回会学习总结webpack2的配置相关总结,有不错的文章欢迎分享。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-03-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Webpack?
    • 入口文件
      • Babel-loader
        • CSS-loader
          • Image loader
            • UglifyJS Plugin(减少输出)
              • 自动打开浏览器&&自动创建index.html
                • 环境标志
                  • Common chunk(抽出公用脚本)
                    • Vendor chunk
                      • 热更新
                        • 有用的链接
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档