The content shared with you in this article is a process analysis of how to build a react scaffolding based on webpack4. The content is very detailed. Next, let’s take a look at the specific content, hoping to help friends in need.
react-sample-javascript
React 16.0 boilerplate with react-router-dom, redux & webpack 4. (for javascript)
github project address
Project initialization
Unify and standardize code format
Configuration
.editorconfig
Make the IDE method unified (see code)-
Configuration
.eslintrc.js
Make the code specifications unified (see code)Expected functions
Manage resources: can load css, sccc, less, and static files
Manage output: Output the packaged static files to the static directory and manage them according to their respective file types
dev: Use source map to facilitate code positioning during debugging
dev: Configure devServer, and configure hot replacement, hot loading, automatic refresh, automatically open the browser, and reserve proxyTable
dev: Set to open 8080 by default. If it is occupied, look for the next empty interface
production: code separation, packaging css files, css code compression, js code compression, output to template html, configure gzip
-
analysis:: Use BundleAnalyzerPlugin to analyze the performance after packaging
Directory structure
First use npm init to initialize a root directory containing package.json
:. │ .babelrc #babel的规则以及插件 │ .editorconfig #IDE/编辑器相关的配置 │ .eslintignore #Eslint忽视的目录 │ .eslintrc.js #Eslint的规则和插件 │ .gitignore #Git忽视的目录 │ .postcssrc.js #postcss的插件 │ package-lock.json │ package.json #项目相关的包 │ README.md │ yarn.lock │ ├─build #webpack相关的配置 │ utils.js #webpack配置中的通用方法 │ webpack.base.conf.js #webpack的基础配置 │ webpack.dev.conf.js #webpack的开发环境配置 │ webpack.prod.conf.js #webpack的生产环境配置 │ └─src #主目录,业务代码 │ app.css │ App.js │ favicon.ico │ index.ejs │ index.js │ └─assets #静态目录,存放静态资源 │ config.json │ └─img logo.svg
Install dependencies
eslint -loader
eslint
eslint-config-airbnb
eslint-plugin-import
eslint-friendly-formatter
eslint-plugin-flowtype
eslint-plugin-jsx -a11y
eslint-plugin-react
- ##babel-polyfill
- webpack
- jest
- friendly-errors-webpack-plugin
Webpack plug-in for compilation prompts
- html-webpack-plugin
Webpack plug-in for creating new html entry files
- copy-webpack-plugin
webpack configuration merge module
- webpack-merge
webpack configuration merge module
- webpack-dev-server
- webpack-bundle-analyzer
- webpack-cli
- portfinder Plug-in to find the interface
- extract-text-webpack-plugin
- node-notifier ##optimize-css-assets-webpack-plugin
- autoprefixer
- mini-css-extract-plugin
- autoprefixer
- css-loader
- less-loader
- postcss-loader
- postcss-import
- postcss-loader
- style-loader
- ##babel-core
- babel-eslint
- babel-loader
##babel-plugin-transform-runtime
babel-plugin-import
babel-preset-env
babel-preset-react
babel-polyfill
url-loader
- ##cross-env
- file-loader
yarn add eslint eslint-loader eslint-config-airbnb eslint-plugin-import eslint-friendly-formatter eslint-plugin-flowtype eslint-plugin-jsx-a11y eslint-plugin-react babel-polyfill webpack jest webpack-merge copy-webpack-plugin html-webpack-plugin friendly-errors-webpack-plugin webpack-dev-server webpack-bundle-analyzer webpack-cli portfinder extract-text-webpack-plugin node-notifier optimize-css-assets-webpack-plugin autoprefixer mini-css-extract-plugin autoprefixer css-loader less-loader postcss-loader postcss-import postcss-loader style-loader babel-core babel-eslint babel-loader babel-plugin-transform-runtime babel-plugin-import babel-preset-env babel-preset-react babel-polyfill url-loader cross-env file-loader -D
- In order to improve the code reuse rate, and to distinguish
basic configuration
and personalized configuration - , you can create new
webpack.base separately
,
webpack.devand
webpack.prodthree configuration files. First configure the most basic entry and output.
module.exports = { context: path.resolve(__dirname, '../'), //绝对路径。__dirname为当前目录。 //基础目录用于从配置中解析入口起点。因为webpack配置在build下,所以传入 '../' entry: { app: ('./src/index.js') //项目的入口 }, output: { path: path.resolve(__dirname, '../dist'), filename: '[name].[hash:8].js', publicPath: '/', libraryTarget: 'umd', }, }
entry
entry can be string, array and object respectively.
// entry为字符串
{
entry: './src/index.js',
output: {
path: '/dist',
filename: 'bundle.js'
}
}
// 结果会生成 '/dist/bundle.js'
// entry为数组,可以添加多个彼此不互相依赖的文件。结合output.library选项,如果传入数组,则只导出最后一项。
{
//如果你在html文件里引入了'bable-polyfill',可以通过数组将它加到bundle.js的最后。
entry: ['./src/index.js', 'babel-polyfill'] ,
output:{
path: '/dist',
filename: 'bundle.js'
}
}
// entry为对象,可以将页面配置为多页面的而不是SPA,有多个html文件。通过对象告诉webpack为每个入口,成一个bundle文件。
// 多页面的配置,可能还要借助于HtmlWebpackPlugin,来指定每个html需要引入的js
{
entry: {
index: './src/index.js'
main: './src/index.js'
login: './src/login.js'
}
output:{
path: '/dist/pages'
filename: '[name]-[hash:5].js' //文件名取自'entry'对象的键名,为了防止推送代码后浏览器读缓存,故再生成的文件之后加上hash码。
}
}
// 会分别生成index.js,main.js,login.js三个文件
Regarding building multiple pages with webpack, you can refer to this article. However, now webpack4.x is also a cliff-edge upgrade. Interested students can search for it by themselves. // entry也可以传入混合类型 { entry:{ vendor: ['jquery','amap','babel-polyfill'] //也可以借助CommonsChunkPlugin提取vendor的chunk。 index: './src/index.js' } output: { path: '/dist' filename: '[name]-[hash:5].js' } }CommonsChunkPlugin was removed after webpack 4.0, you can use splitChunksPlugin instead. outputThe two most basic configurations of output are
path
andfilename
:path
- dist
- folder in the root directory;
Used to specify the file name of the output file. If multiple separatefilename
chunk - are configured, you can use placeholders like
[name].[hash]
to ensure that each Each file has a unique name;
另一个常见配置
publicPath
则是用于更加复杂的场景。举例:在本地时,你可能会使用../assets/test.png
这种url来载入图片。而在生产环境下,你可能会使用CDN或者图床的地址。那么就需要配置publicPath = "http://cdn.example.com/assets/"
来实现生产模式下编译输出文件时自动更新url。
output: { path: path.resolve(__dirname, '../dist'), filename: '[name].[hash:8].js', publicPath: '/', },
resolve
resolve常用的两个配置为 alias
和 extensions
:
alias
创建import或者require的别名extensins
自动解析文件拓展名,补全文件后缀
resolve: { // 自动解析文件扩展名(补全文件后缀)(从左->右) // import hello from './hello' (!hello.js? -> !hello.jsx? -> !hello.json) extensions: ['.js', '.jsx', '.json'], alias: { '@': resolve('src') } },
module
module的选项决定了如何处理项目中的不同类型的模块。其中常用的有 rules
和 noParese
两个配置项。
noParese
是为了防止weback解析与所有与rule相匹配的文件。目的是,忽略大型的library可以提高构建性能。
noParse: function(content) { return /jquery|lodash/.test(content); }
rules
用于在创建模块是,匹配规则数组,以确定哪些规则能够对module应用loader,或者是修改parser。
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 } }] }, { test: /\.css$/, include: /node_modules/, use: [ MiniCssExtractPlugin.loader, 'css-loader', { loader: 'postcss-loader', options: { plugins: () => [autoprefixer({ browsers: 'last 5 versions' })], sourceMap: false, }, }, ], }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: ('assets/img/[name].[hash:7].[ext]') } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: ('assets/media/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: ('assets/fonts/[name].[hash:7].[ext]') } } ] }
例如上述代码,就使用eslint-lodaer
和 babel-loader
处理了除了node_modules
以外的 js||jsx
。同时配置了,解析图片、视频、字体文件等的解析,当rules匹配到的文件时,小于10000 byte 时,采用url-loader解析文件。(因为base64会让图片的体积变大,所以当文件较大时,使用base64并不明智)
Webpack开发配置
因为在webpack 4.X 中使用了流行的 ”约定大于配置“ 的做法,所以在新加入配置项 mode
,可以告知webpack使用相应模式的内置优化。
选项 | 描述 |
---|---|
development |
会将process.env.NODE_ENV 的值设为 development 。启用NamedChunksPlugin 和 NamedMoudulesPlugin 。 |
production |
会将process.env.NODE_ENV 的值设为 production 。启用FlagDependencyUsagePlugin ,FlagIncludedChunksPlugin ,ModuleConcatenationPlugin ,NoEmitOnErrorsPlugin ,OccurrenceOrderPlugin ,SideEffectsFlagPlugin 和UglifyJsPlugin 。 |
如果我们只设置NODE_ENV,则不会自动设置 mode
在开发时,我们往往希望能看到当前开发的页面,并且能热加载。这时,我们可以借助webpack-dev-server 这个插件,来在项目中起一个应用服务器。
// package.json "scripts": { "start": "webpack-dev-server --mode development --config build/webpack.dev.conf.js", } // 设置当前的mode为development,同样这个配置也可以写在webpack.dev.conf.js中。然后使用build目录下的webpack.dev.conf.js 来配置相关的webpack。
devServer: { clientLogLevel: 'warning', historyApiFallback: true, //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html contentBase: path.resolve(__dirname, '../src'), compress: true, hot: true, // 热加载 inline: true, //自动刷新 open: true, //自动打开浏览器 host: HOST||'localhost', port: PORT, overlay: { warnings: false, errors: true }, // 在浏览器上全屏显示编译的errors或warnings。 publicPath: '/', proxy: {}, quiet: true, // necessary for FriendlyErrorsPlugin // 终端输出的只有初始启动信息。 webpack 的警告和错误是不输出到终端的 watchOptions: { poll: false } }, plugins: [ new webpack.DefinePlugin({ ...process.env }), //开启HMR(热替换功能,替换更新部分,不重载页面!) new webpack.HotModuleReplacementPlugin(),// HMR shows correct file names in console on update. //显示模块相对路径 new webpack.NamedModulesPlugin(), //不显示错误信息 new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin ]
其实在开发时,我们可以设置 contentBase: '/src'
,contentBase
指定了devServer能访问的资源地址。因为我们开发时,资源大部分都放在src
目录下,所以可以直接指定资源路径为src
目录。因为我们在webpack基础配置时,配置了 output
输出为 dist
目录,所以我们也可以在devServer里,设置 contentBase
为 dist
目录。不过此时需要使用copyWebpackPlugin将一些静态资源复制到 dist
目录下,手动新建dist目录,并复制也可以。
另外,当使用 history 路由时,要配置 historyApiFallback = true
,以此让服务器放弃路由权限,交由前端路由。而是用 hash 路由则不需要此配置。
项目进阶
生产环境配置
在使用webpack 4.x 的 mode 配置之后,需要我们手动配置的项已经减少了很多,像js代码压缩这种工具 UglifyJsPlugin
就已经不用手动去配置。但是像很多前面提到的 代码分离
、css代码提取和压缩
、html的生成
以及 复制静态资源
还需要我们手动配置。
代码分离
// 设置代码分离的输出目录 output: { path: path.resolve(__dirname, '../dist'), filename: ('js/[name].[hash:8].js'), chunkFilename: ('js/[name]-[id].[hash:8].js') }, // 代码分离 optimization: { runtimeChunk: { name: "manifest" }, splitChunks: { chunks: 'all' } },
css代码压缩
借助 MiniCssExtractPlugin
来实现压缩css和提取css。因为 MiniCssExtractPlugin
无法与style-loader 共存,所以我们需要判断当前环境是生成环境还是开发环境。
我们可以新建一个util.js的文件,在webpack当中一些共用的方法。考虑使用个别配置字段 extract
来配置使用何种方式来配置css-loader。参见 util.js
代码。
new MiniCssExtractPlugin({ filename: 'css/[name].[hash:8].css', chunkFilename: 'css/[name]-[id].[hash:8].css', }),
生成HTML
使用htmlWebpackPlugin
,配合ejs。可以使控制html 的生成。通过配置的方式,生成html。因为 HtmlWebpackPlugin
本身可以解析ejs,所以不需要单独引入ejs的loader。
new HtmlWebpackPlugin({ filename: 'index.html', template: './src/index.ejs', // 设置目录 title: 'React Demo', inject: true, // true->'head' || false->'body' minify: { //删除Html注释 removeComments: true, //去除空格 collapseWhitespace: true, //去除属性引号 removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }),
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="robots" content="noindex, nofollow"> <title><%= htmlWebpackPlugin.options.title %></title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="icon" href="/favicon.ico" type="image/x-icon"> <% for (var chunk in htmlWebpackPlugin.files.css) { %> <link rel="preload" href="<%= htmlWebpackPlugin.files.css[chunk] %>" as="style"> <% } %> <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> <link rel="preload" href="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>" as="script"> <% } %> <base href="/"> </head> <body> <p id="root"></p> </body> <style type="text/css"> body { font-family: 'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif; } </style> </html>
复制静态目录
将所以可能被请求的静态文件,分别放在assets目录下。那么在打包后,为了保证目录能正常访问(不使用CDN等加载静态资源时),我们可以配置 publicPath = '/'
。然后借助于 CopyWebpackPlugin
实现资源复制。
new CopyWebpackPlugin([{ from: './src/assets/', to: 'assets' }]),
将 src/assets
复制到 dist/assets
目录下
开启打包分析
借助插件 BundleAnalyzerPlugin
直接在plugins中创建该插件:
// webpack.prod.conf.js const BundleAnalyzerPlugin = process.env.NODE_ENV=== 'analysis' ? require('webpack-bundle-analyzer').BundleAnalyzerPlugin:null process.env.NODE_ENV=== 'analysis' ? new BundleAnalyzerPlugin() : ()=>{}
在package.json 中可做如下配置:
"scripts": { "analysis": "cross-env NODE_ENV=analysis webpack -p --mode production --progress --config ./build/webpack.prod.conf.js ", },
通过注入环境变量,来控制是否运行打包分析。
ssh部署
打包后的dist文件夹,可以直接借助 node 的 ssh-node ,直接部署到服务器指定的目录下。 ssh-node既支持ssh,也支持密码登录。建议可以为在每个项目下,新建一个.ssh文件,存放项目的私钥。代码如下:
// usage: https://www.npmjs.com/package/node-ssh var path, node_ssh, ssh, fs, opn, host fs = require('fs') path = require('path') node_ssh = require('node-ssh') opn = new require('opn') ssh = new node_ssh() host = 'localhost' var localDir = './dist' var remoteDir = '/opt/frontend/new' var removeCommand = 'rm -rf ./*' var pwdCommand = 'pwd' ssh.connect({ host: host, username: 'root', port: 22, // password, privateKey: "./.ssh/id_rsa", }) .then(function() { ssh.execCommand(removeCommand, { cwd:remoteDir }).then(function(result) { console.log('STDOUT: ' + result.stdout) console.log('STDERR: ' + result.stderr) ssh.putDirectory(localDir, remoteDir).then(function() { console.log("The File thing is done") ssh.dispose() opn('http://'+host, {app:['chrome']}) }, function(error) { console.log("Something's wrong") console.log(error) ssh.dispose() }) }) })
此时,在命令行直接 node deploy.js
就可以运行以上脚本,我们也可以添加一个build + deploy的script脚本,便于启动。
"scripts": { "depoly": "npm run build && node ./deploy.js", }
相关推荐:
详解React 快速上手脚手架 create-react-app
The above is the detailed content of Process analysis of how to build a react scaffolding based on webpack4. For more information, please follow other related articles on the PHP Chinese website!

Detailed explanation of JavaScript string replacement method and FAQ This article will explore two ways to replace string characters in JavaScript: internal JavaScript code and internal HTML for web pages. Replace string inside JavaScript code The most direct way is to use the replace() method: str = str.replace("find","replace"); This method replaces only the first match. To replace all matches, use a regular expression and add the global flag g: str = str.replace(/fi

This tutorial shows you how to integrate a custom Google Search API into your blog or website, offering a more refined search experience than standard WordPress theme search functions. It's surprisingly easy! You'll be able to restrict searches to y

So here you are, ready to learn all about this thing called AJAX. But, what exactly is it? The term AJAX refers to a loose grouping of technologies that are used to create dynamic, interactive web content. The term AJAX, originally coined by Jesse J

This article series was rewritten in mid 2017 with up-to-date information and fresh examples. In this JSON example, we will look at how we can store simple values in a file using JSON format. Using the key-value pair notation, we can store any kind

Leverage jQuery for Effortless Web Page Layouts: 8 Essential Plugins jQuery simplifies web page layout significantly. This article highlights eight powerful jQuery plugins that streamline the process, particularly useful for manual website creation

Core points This in JavaScript usually refers to an object that "owns" the method, but it depends on how the function is called. When there is no current object, this refers to the global object. In a web browser, it is represented by window. When calling a function, this maintains the global object; but when calling an object constructor or any of its methods, this refers to an instance of the object. You can change the context of this using methods such as call(), apply(), and bind(). These methods call the function using the given this value and parameters. JavaScript is an excellent programming language. A few years ago, this sentence was

jQuery is a great JavaScript framework. However, as with any library, sometimes it’s necessary to get under the hood to discover what’s going on. Perhaps it’s because you’re tracing a bug or are just curious about how jQuery achieves a particular UI

This post compiles helpful cheat sheets, reference guides, quick recipes, and code snippets for Android, Blackberry, and iPhone app development. No developer should be without them! Touch Gesture Reference Guide (PDF) A valuable resource for desig


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 Linux new version
SublimeText3 Linux latest version

SublimeText3 Chinese version
Chinese version, very easy to use

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Mac version
God-level code editing software (SublimeText3)
