webpack配置React开发环境(上)
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
的配置文件。
// 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字段,如下所示:
// package.json { // ... "scripts": { "dev": "webpack-dev-server --devtool eval --progress --colors", "deploy": "NODE_ENV=production webpack -p" }, // ... }
入口文件
入口文件是一个Webpack将会读取它并将它编译成bundle.js的文件
demo01:单个入口文件:
// webpack.config.js module.exports = { entry: './main.js', output: { filename: 'bundle.js' } };
demo02:多个入口文件:(它对多页面app是非常有用的)
// 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文件。官方文档有一个完整的加载器列表。
// 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文件。
// main.js require('./app.css');
// 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
// 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。
<img src="data:image/png;base64,iVBOR...uQmCC"> <img src="4853ca667a2b8b8844eb2693ac1b2578.png">
UglifyJS Plugin(减少输出)
Webpack有一个插件系统来扩展其功能。例如,UglifyJs Plugin将缩小输出(bundle.js)JS代码。(demo07)
// 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 } }) ] };
压缩的效果如下:
// 压缩前 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可以打开一个新的浏览器选项卡。
// 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)
// 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。
# Linux & Mac $ env DEBUG=true webpack-dev-server # Windows $ set DEBUG=true $ webpack-dev-server
Common chunk(抽出公用脚本)
当多脚本具有公共块时,可以使用CommonsChunkPlugin将公共部分提取到单独的文件中。
// 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从脚本中将供应商库提取到单独的文件中。(优化代码层面)
// 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(官方文档)。
// 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
$ 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 到输入字段
// 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, '.') }] } };
// 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>
有用的链接
- Webpack docs
- webpack-howto
- Diving into Webpack
- Webpack and React is awesome
- Browserify vs Webpack
- React Webpack cookbook
下回会学习总结webpack2的配置相关总结,有不错的文章欢迎分享。
作者:牧云云
出处:http://www.cnblogs.com/MuYunyun/"
本文版权归作者和博客园所有,欢迎转载,转载请标明出处。
如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构