从零开始搭建一个react项目
准备工作
初始化工程从这里开始新建一个react工程 1. 初始化工程目录1 cd react-demo 2 npm init ? 一路回车,我们将得到一个最简单的npm目录,会包含一个package.json。 // package.json { "name": "react-demo","version": "1.0.0","description": "","main": "index.js","scripts": { "test": "echo "Error: no test specified" && exit 1" },"author": "","license": "ISC" } ? 然后在react-demo目录下新建一个程序的主目录" src " 目录。 2. 配置工程1. webpack初体验首先安装webpack和webpack-cli。 webpack4.X npm install --save-dev webpack webpack-cli -g
?
新建并配置webpack新建webpack.config.js 文件。首先要理解webpack的几个基础概念入口(entry)、出口(output)、载入器(loader)、插件(plugins)、模式(mode) 。webpack中文文档。代码如下: 1 // __dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 2 // path是node.js中提供的处理文件路径的小工具。 (http://www.runoob.com/nodejs/nodejs-path-module.html) 3 const path = require(‘path‘); 4 module.exports = { 5 // 项目入口,webpack从此处开始构建 6 entry: { 7 main: path.join(__dirname,‘src/index.js‘),// 指定入口,可以指定多个。参考webpack文档 8 }, 9 output: { 10 path: path.join(__dirname,"dist"),// bundle生成(emit)到哪里 11 filename: "bundle.js",// bundle生成文件的名称 12 },13 } ?
配置开发应用服务器正常情况下,我们需要以应用服务器打开我们的网页,webpack-dev-server提供了一个简单的web服务器,并且能够实时重新加载。指南 首先需要安装webpack-dev-server 1 // webpack.config.js 2 module.exports = { 3 devServer: { 4 contentBase: ‘./dist‘ 5 } 6 } ? 这段配置告诉webpack-dev-server,在默认host和port下建立服务,并将contentBase目录下的目录,作为可访问文件。 1 "scripts" : { 2 "start": "webpack-dev-server --mode development --open",3 "build: "webpack --mode production --config ./webpack.config.js" 4 } ? 其中mode是上文中提到模式概念,webpack会有相应的内置优化。 Babel & ReactES6已经极为流行了,不过目前仍有浏览器不兼容。同时react的jsx语法,也需要babel来将其转化为能兼容的js代码。 1 npm install react react-dom react-router-dom -S 2 npm install babel-core babel-loader babel-preset-env babel-preset-react -D ? 安装完之后,我们需要在webpack中配置使其生效。在webpack.config.js 的module中添加rules规则,如下: module.exports = { // ...省略 module: { rules: [ { test: /.(js|jsx)$/,exclude: /node_modules/,enforce: ‘pre‘,use: [{ loader: ‘babel-loader‘,},{ loader: ‘eslint-loader‘,// 指定启用eslint-loader options: { formatter: require(‘eslint-friendly-formatter‘),emitWarning: false } }] },] } ? 使用babel-loader我们需要配置相应的规则,我们可以这样配置: 同时考虑到,后期可能会别的规则需求,例如使用antDesign的按需引入,我们将babel的配置提出来,在根目录下新建文件 .babelrc ,并书写以下代码。
{
"presets": ["env","react"],// antd按需引入
// "plugins": ["react-hot-loader/babel",["import",{ "libraryName": "antd","libraryDirectory": "es","style": "css" }],"transform-runtime"]
}
? 到这里,我们就完成babel的相关配置,并且安装了react相关依赖,可以书写jsx语法了。 关于样式前置安装less-loader/scss-loader、style-loader、css-loader、postcss-loader。
test: /.(css|less)$/,include: /src/,use: [ {loader: "style-loader"},{ loader: ‘css-loader‘,options: { minimize: process.env.NODE_ENV === ‘production‘,importLoaders: 2,localIdentName: ‘[name]-[local]-[hash:base64:5]‘,modules:true } },{ loader: ‘postcss-loader‘,options: { // 如果没有options这个选项将会报错 No PostCSS Config found plugins: (loader) => [ require(‘autoprefixer‘)(),//CSS浏览器兼容 ] } },{ loader: ‘less-loader‘,options: { javascriptEnabled: true,} }], ? 其中test对应的可以匹配的正则文件,include是需要编译的目录,exclude是跳过的目录,use里面可以书写跟loader相关的配置。
至此,完成了一个简单的react工程的配置。只包含有js和css相关的内容。 工程优化
ExtractTextWebapckPlugin在上面的配置中,我们没有单独打包样式文件,样式文件会被打包在js里面。现在通过ExtractTextWebpackPlugin单独打包样式文件。 // module-> rules { test: /.less$/,// loader:[‘style-loader‘,‘css-loader‘] use: ExtractTextWebapckPlugin.extract({ fallback:‘style-loader‘,use: [ { loader: ‘css-loader‘,options: { minimize: process.env.NODE_ENV === ‘production‘,modules:true } },{ loader: ‘postcss-loader‘,options: { // 如果没有options这个选项将会报错 No PostCSS Config found plugins: (loader) => [ require(‘autoprefixer‘)(),//CSS浏览器兼容 ] } },{ loader: ‘less-loader‘,options: { javascriptEnabled: true,} }],} ) },// plugins 下新增 new ExtractTextWebapckPlugin({ filename: ‘css/[name]-[hash].css‘,// Setting the following option to `false` will not extract CSS from codesplit chunks. // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. // It‘s currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it‘s `false`, allChunks: true }), ? 为打包后的文件增加hash如果浏览器加载发现远端文件没有发生变化时,将会启用缓存,导致新修改的页面并没有同步,这时候为了避免缓存,我们就需要让每次打包后的文件有不同的文件名,以减少缓存。 // webpack.config.js -> output output: { path: path.join(__dirname,"dist"),publicPath: ‘/‘,filename: "js/[name]-[hash]" + ".js",chunkFilename: "js/[name]-[hash]" + ".js", ? 打包静态文件当页面图片较多时,会发送很多http请求,降低页面性能。url-loader引入图片编码,生成dataURI,把图片翻译成一串字符串。再把字符串打包到文件中,最终只需要引入文件就可以访问图片了。但是当图片较大时,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit的文件会被转为dataURI,大于limit会使用file-loader传入。首先引入依赖 // module->rules { test: /.(png|jpe?g|gif|svg)(?.*)?$/,loader: ‘url-loader‘,options: { limit: 10000,name: ‘static/img/[name].[hash:7].[ext]‘ } },{ test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,name: ‘static/media/[name].[hash:7].[ext]‘ } },{ test: /.(woff2?|eot|ttf|otf)(?.*)?$/,name: ‘static/fonts/[name].[hash:7].[ext]‘ } }, ? html-webpack-plugin这是一个 webpack 插件,为我们在生成有 hash 标识符的 css,js时非常方便,它需要我们指定一个模板,然后它会生成一个自动引入我们生成的文件的新模板。 const HtmlWebPackPlugin = require(‘html-webpack-plugin‘) // plugins下添加 new HtmlWebPackPlugin({ template: ‘./src/index.html‘,minify: { removeComments: true,collapseWhitespace: true,removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference },filename: ‘index.html‘ }), ? devServer开发服务器配置如下: // webpack.config.js devServer: { // contentBase: path.join(__dirname,""), contentBase: false,//since we use CopyWebpackPlugin. clientLogLevel: ‘warning‘,hot: true,progress: true,overlay: { warnings: false,errors: true },historyApiFallback: { rewrites: [ { from: /.*/,to: path.posix.join(‘/‘,‘index.html‘) },],// historyApiFallback: true, // quiet: true,// necessary for FriendlyErrorsPlugin compress: true,inline: true,port: 8083,host: ‘127.0.0.1‘,watchOptions: { poll: false,} }, ? 因为配置了contentBase = false,所以使用CopyWebpackPlugin,还是先安装依赖 // plugins // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname,‘./src/static‘),to: ‘static‘,ignore: [‘.*‘] } ]), ? 提取公共代码利用webpack4的splitChunks来分割代码,配置如下: // webpack.config.js //4.0配置 optimization: { /*splitChunks: { chunks: ‘all‘,//"initial" | "async" | "all" cacheGroups: { default: false,vendors: false,*/ /*splitChunks: { cacheGroups: { commons: { test: /[/]node_modules[/]/,name: "vendor",chunks: "all" } } }*/ runtimeChunk: { name: "manifest" },splitChunks: { cacheGroups: { commons: { test: /[/]node_modules[/]/,name: "vendor",chunks: "all" } } } }, ? ?
来自为知笔记(Wiz)
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |