React + Webpack (jsx +less)
Posted System.print("宇航")
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React + Webpack (jsx +less)相关的知识,希望对你有一定的参考价值。
React项目的初始化、webpack的安装、如何使用jsx和less。
一、初始 React 项目
react项目的初始化比较简单,我用的就是react的脚手架。三种方式:
1、NPM
npm init react-app my-app
2、NPX
npx create-react-app my-app
3、Yarn
yarn create react-app my-app
my-app 是项目的名字,运行命令时会在当前目录下自动创建一个名字叫作 my-app 的项目文件夹。命令运行完毕,简单的React项目就初始化完成了。项目的初始的代码结构式这个样子的:
进入项目文件,你可以通过 npm run start 来运行项目,会跳出一个React的欢迎页
my-app ├── README.md ├── node_modules ├── package.json ├── .gitignore ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js
二、Webpack安装程序
Webpack
WebPack可以看做是模块打包机:它会分析你的项目结构,找到javascript模块以及其它的一些浏览器不能直接运行的拓展语言(less、jsx、Scss、TypeScript等),并将其打包为合适的格式以供浏览器使用。
为什么要用 WebPack ?
1、模块化
在webpack看来一切都是模块!这就是它不可不说的优点,包括你的JavaScript代码,也包括CSS和fonts以及图片等等等,只有通过合适的loaders,它们都可以被当做模块被处理。
2、预处理(Less,Sass,ES6,TypeScript……)
3、主流框架脚手架支持(Vue,React,Angular)
4、庞大的社区(资源丰富,降低学习成本)
1、开始安装Webpack
使用 webpack 首先你需要安装 webpack-dev-server 在本地环境中为捆绑的应用程序提供服务、webpack-cli 在配置文件中来配置你的Webpack 设置。
npm install --save-dev webpack webpack-dev-server webpack-cli
2、修改 package.json
主要修改 package.json 中的启动项
"scripts": { "start": "webpack-dev-server --config config/webpack.base.config.js --mode development", ... }
脚本将 webpack-dev-server 与名为 webpack.base.config.js 一起使用。我在项目的根目录下创建了一个 config 文件夹,里面用来存放 webpack 的配置文件。The --mode development
flag just adds default Webpack configurations which came with Webpack 4.
3、编辑 webpack.base.config.js
module.exports = { entry: \'./src/index.js\', output: { path: __dirname + \'/public\', publicPath: \'/\', filename: \'bundle.js\' }, devServer: { contentBase: \'./public\' } };
文件说明:
(1) 我们希望使用 “./src/index.js” 文件作为入口点。
(2) 绑定的文件最后生成的js文件,叫做: bundle.js .
(3)生成的位置在:“/public”
4、修改一下public/index.html 和 src/index.js 中的内容
因为我们初步使用 webpack 来启动我们的项目,所以像是 svg图片、react的识别都还没有配置。所以先将这两个文件进行修改,这些修改不会影响到之后咱们的搭建。将两个文件修改成下面的样子。
public/index.html
<!DOCTYPE html> <html lang="en"> <head> <title>React App</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <base href="/"> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <script src="./bundle.js"></script> </body> </html>
src/index.js
console.log(\'My Minimal React Webpack Babel Setup\');
5、npm start
OK,我们已经使用 webpack 将项目的启动脚本配置好了。下面就是使用 npm start 来验证我们的启动命令是否成功。
项目启动成功,接下来访问地址 localhost:8080 来访问一下。
其中我们在 src/index.js 里面 console.log 的信息已经显示在了浏览器里边,说明 index.js 已经通过 webpack 编译成了 bundle.js。
三、配置 babel
babel 是一个广泛的转码器,可以将 ES6 代码转化为 ES5 代码。从而在现有的环境中执行。
1、安装插件
在项目根目录下指定下面命令,作用是使得 babel 正常执行:
npm install --save-dev @babel/core @babel/preset-env
为了将它连接到Webpack,还需要安装一个加载器:
npm install --save-dev babel-loader
还需要一个配置,来将 React 的 jsx 语法转化成 JavaScript:
npm install --save-dev @babel/preset-react
2、编辑 webpack.base.config.js 文件
在 webpack.base.config.js 文件中添加代码:
module: { rules: [ { test: /\\.(js|jsx)$/, exclude: /node_modules/, use: [\'babel-loader\', \'eslint-loader\'] }, { test: /\\.(css|less)$/, use:["style-loader", "css-loader", "less-loader"] }, { test: /\\.svg$/, use: [\'file-loader\'] } ] }, resolve: { extensions: [\'*\', \'.js\', \'.jsx\', \'.css\', \'.less\'] }
这些代码的作用是 是代码识别 js、jsx、css、less、svg图片文件的。
这里要下载几个 loader 和 plugin:
npm install --save-dev style-loader css-loader less less-loader eslint-loader file-loader extract-text-webpack-plugin@next
在项目根目录下创建 .babelrc
文件
.babelrc
{ "presets": [ "@babel/preset-env", "@babel/preset-react" ] }
3、修改 src/index.js 文件
webpack 已经认less和css文件了。现在我们修改一下index.js
import React from \'react\'; import ReactDOM from \'react-dom\'; import \'./index.css\'; import App from \'./App\'; import * as serviceWorker from \'./serviceWorker\'; ReactDOM.render(<App />, document.getElementById(\'root\')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
然后将 App.css 改名为 App.less, 内容不需要改,如下图:
OK,现在执行命令 npm start,访问 localhost:8080 看一下结果.
成功。
四、使用 webpack 打包项目
1、首先我在 config 文件夹中创建 path.js、webpack.opt.config.js、 webpack.prod.config.js 三个文件
path.js
path 的作用是 提供path路径的,自定义的path。
var path = require(\'path\'); var fs = require(\'fs\'); // Make sure any symlinks in the project folder are resolved: // https://github.com/facebookincubator/create-react-app/issues/637 var appDirectory = fs.realpathSync(process.cwd()); function resolveApp(relativePath) { return path.resolve(appDirectory, relativePath); } // We support resolving modules according to `NODE_PATH`. // This lets you use absolute paths in imports inside large monorepos: // https://github.com/facebookincubator/create-react-app/issues/253. // It works similar to `NODE_PATH` in Node itself: // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders // We will export `nodePaths` as an array of absolute paths. // It will then be used by Webpack configs. // Jest doesn\'t need this because it already handles `NODE_PATH` out of the box. // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 var nodePaths = (process.env.NODE_PATH || \'\') .split(process.platform === \'win32\' ? \';\' : \':\') .filter(Boolean) .filter(folder => !path.isAbsolute(folder)) .map(resolveApp); // config after eject: we\'re in ./config/ module.exports = { appBuild: resolveApp(\'build\'), appPublic: resolveApp(\'public\'), appHtml: resolveApp(\'public/index.html\'), appIndexJs: resolveApp(\'src/index.js\'), appPackageJson: resolveApp(\'package.json\'), appSrc: resolveApp(\'src\'), yarnLockFile: resolveApp(\'yarn.lock\'), appNodeModules: resolveApp(\'node_modules\'), nodePaths: nodePaths };
webpack.opt.config.js
webpack.opt.config.js 是在打包时做 css代码 优化的
var OptimizeCssAssetsPlugin = require(\'optimize-css-assets-webpack-plugin\'); var UglifyJsPlugin = require(\'uglifyjs-webpack-plugin\'); module.exports = { optimization: { minimizer: [ new UglifyJsPlugin({ uglifyOptions: { mangle: { keep_fnames: true, }, }, }) ], }, plugins: [ new OptimizeCssAssetsPlugin() ], }
webpack.prod.config.js
webpack.prod.config.js 用来将各个 config 文件融合到一起
var webpack = require(\'webpack\');
var merge = require(\'webpack-merge\');
var baseConfig = require(\'./webpack.base.config\');
var optimizationConfig = require(\'./webpack.opt.config\');
const productionConfiguration = function (env) {
const NODE_ENV = env.NODE_ENV ? env.NODE_ENV : \'development\';
return {
plugins: [
new webpack.DefinePlugin({ \'process.env.NODE_ENV\': JSON.stringify(NODE_ENV) }),
]
};
}
module.exports = merge.smart(baseConfig, optimizationConfig, productionConfiguration);
安装 uglifyjs-webpack-plugin 和 webpack-merge :
npm install --save-dev uglifyjs-webpack-plugin
npm install --save-dev webpack-merge
2、在项目根目录下创建 server 文件夹
server 的作用是,打包成功之后,项目启动一个server。可以通过访问 server 地址来直接访问项目build之后生成的包。
server/index.js
const express = require(\'express\'); const path = require(\'path\'); const http = require(\'http\'); const app = express(); // Point static path to dist app.use(express.static(path.join(__dirname, \'..\', \'build\'))); const routes = require(\'./routes\') app.use(\'/\', routes); /** Get port from environment and store in Express. */ const port = process.env.PORT || \'3000\'; app.set(\'port\', port); /** Create HTTP server. */ const server = http.createServer(app); /** Listen on provided port, on all network interfaces. */ server.listen(port, () => console.log(`Server Running on port ${port}`))
routes/index.js
const path = require(\'path\'); const router = require(\'express\').Router(); router .get(\'/*\', (req, res, next) => { const routePath = path.join(__dirname + \'..\', \'..\', \'..\',\'build/\' + \'index.html\'); res.sendFile(routePath); }) module.exports = router;
这里面要安装一个 express:
npm install --save-dev express
3、修改 webpack.base.config.js
webpack.base.config.js 最终版
const webpack = require(\'webpack\');
var HtmlWebpackPlugin = require(\'html-webpack-plugin\');
var ExtractTextPlugin = require(\'extract-text-webpack-plugin\');
var paths = require(\'./paths\');
module.exports = {
entry: \'./src/index.js\',
output: {
path: paths.appBuild,
publicPath: \'/\',
filename: \'bundle.js\'
},
module: {
rules: [
{
test: /\\.(js|jsx)$/,
exclude: /node_modules/,
use: [\'babel-loader\', \'eslint-loader\']
},
{
test: /\\.(css|less)$/,
use:["style-loader", "css-loader", "less-loader"]
// use: ExtractTextPlugin.extract({
// fallback: "style-loader",
// use: "css-loader!less-loader",
// })
},
{
test: /\\.svg$/,
use: [\'file-loader\']
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: \'./public/index.html\',
filename: \'./index.html\'
}),
new ExtractTextPlugin(\'style.css\')
],
resolve: {
extensions: [\'*\', \'.js\', \'.jsx\', \'.css\', \'.less\']
},
devServer: {
contentBase: \'./public\',
hot: true
}
};
标红的部分是两种 css 的 load 方式。
直接使用 " use: [] " : 打包时,css会被打包到 bundle.js 里面。
使用 " use: ExtractTextPlugin.extract() " : 和 plugin 中的 new ExtractTextPlugin(\'style.css\') 联用。打包时会将css文件分离开来进行打包,在 build 文件夹中生成一个 style.css 文件.
安装 html-webpack-plugin:
npm install --save-dev html-webpack-plugin
4、package.json
将 script 中的 build 换成如下语句:
"prestart:prod": "webpack --mode production --config config/webpack.prod.config.js --env.NODE_ENV=production --progress", "start:prod": "node server",
5、测试
OK,全部配置完毕了,下面我们来测试一下是否成功。
运行命令 npm run start:prod
build 生成的文件,三个如下:
运行成功,访问 localhost:3000 访问 build 好的包。
执行命令: npm start
访问 localhost:8080:
以上是关于React + Webpack (jsx +less)的主要内容,如果未能解决你的问题,请参考以下文章
react+webpack+scss 怎么编译css独立文件
React开发环境搭建(react,babel,webpack webpack-dev-server)