博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从 roadhog 转移到 create-react-app 并升级 webpack4
阅读量:6094 次
发布时间:2019-06-20

本文共 11882 字,大约阅读时间需要 39 分钟。

从 roadhog 转移到 create-react-app 并升级 webpack4

项目环境说明

公司项目,使用 antd 做为开发的 UI 框架, 项目使用预编译语言 less,这主要是为了和 antd 官方保持一致,

项目中有一些 tsx 的组件和 一些 ts 的脚本,所以 新的配置必须能够适应 js 和 ts 混合编译,支持
css-modules, 支持 less 以及 antd 的动态导入

完整开发配置

eject 配置

$ yarn eject # npm run eject

开启自定义配置

webpack.config.dev.js

其中纯 CRA 配置不存在自定义,不过把原有 CRA 的配置都升级到 webpack4 的版本上了。其中包含了 webpack

的配置特点,以及如何解决 css-modules 和 antd 的动态样式导入的冲突

// webpack.config.dev.js'use strict'const autoprefixer = require('autoprefixer')const path = require('path')const webpack = require('webpack')const HtmlWebpackPlugin = require('html-webpack-plugin')const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin')const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin')const eslintFormatter = require('react-dev-utils/eslintFormatter')const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')const tsImportPluginFactory = require('ts-import-plugin')const getClientEnvironment = require('./env')const paths = require('./paths')const publicPath = '/'const publicUrl = ''const env = getClientEnvironment(publicUrl)module.exports = {  mode: 'development',  devtool: 'cheap-module-source-map',  entry: [    require.resolve('./polyfills'),    require.resolve('react-dev-utils/webpackHotDevClient'),    paths.appIndexJs,  ],  output: {    pathinfo: true,    filename: 'static/js/bundle.js',    chunkFilename: 'static/js/[name].chunk.js',    publicPath: publicPath,    devtoolModuleFilenameTemplate: (info) =>      path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),  },  resolve: {    modules: ['node_modules', paths.appNodeModules].concat(      process.env.NODE_PATH.split(path.delimiter).filter(Boolean)    ),    extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.ts', '.tsx'],    alias: {      'react-native': 'react-native-web',    },    plugins: [new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson])],  },  module: {    strictExportPresence: true,    rules: [      {        oneOf: [          {            test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],            loader: require.resolve('url-loader'),            options: {              limit: 10000,              name: 'static/media/[name].[hash:8].[ext]',            },          },          {            test: /\.(ts|tsx)$/,            use: [              {                loader: require.resolve('awesome-typescript-loader'),                options: {                  transpileOnly: true,                  useCache: true,                  useBabel: true,                  babelOptions: {                    babelrc: true,                  },                  babelCore: '@babel/core',                },              },            ],            exclude: /node_modules/,          },          {            test: /\.(js|jsx|mjs)$/,            include: paths.appSrc,            // loader: 'happypack/loader',            loader: require.resolve('babel-loader'),            query: {              cacheDirectory: true,              // plugins: [['import', { libraryName: 'antd', style: true }]],            },          },          {            test: /\.css$/,            use: [              require.resolve('style-loader'),              {                loader: require.resolve('css-loader'),                options: {                  importLoaders: 1,                  modules: true,                  localIdentName: '[name]__[local]___[hash:base64:5]',                },              },              {                loader: require.resolve('postcss-loader'),                options: {                  ident: 'postcss',                  plugins: () => [                    require('postcss-flexbugs-fixes'),                    autoprefixer({                      browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9'],                      flexbox: 'no-2009',                    }),                  ],                },              },            ],          },          {            test: /\.less$/,            exclude: path.resolve(__dirname, '../node_modules'),            use: [              require.resolve('style-loader'),              {                loader: require.resolve('css-loader'),                options: {                  importLoaders: 1,                  modules: true,                  localIdentName: '[name]__[local]___[hash:base64:5]',                },              },              {                loader: require.resolve('postcss-loader'),                options: {                  ident: 'postcss',                  plugins: () => [                    require('postcss-flexbugs-fixes'),                    autoprefixer({                      browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9'],                      flexbox: 'no-2009',                    }),                  ],                },              },              {                loader: require.resolve('less-loader'),                options: {                  modifyVars: { '@primary-color': '#1DA57A' },                  javascriptEnabled: true,                },              },            ],          },          {            test: /\.less$/,            include: [path.resolve(__dirname, '../node_modules/')],            use: [              require.resolve('style-loader'),              {                loader: require.resolve('css-loader'),                options: {                  importLoaders: 1,                },              },              {                loader: require.resolve('postcss-loader'),                options: {                  ident: 'postcss',                  plugins: () => [                    require('postcss-flexbugs-fixes'),                    autoprefixer({                      browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9'],                      flexbox: 'no-2009',                    }),                  ],                },              },              {                loader: require.resolve('less-loader'),                options: {                  modifyVars: { '@primary-color': '#1DA57A' },                  javascriptEnabled: true,                },              },            ],          },          {            exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],            loader: require.resolve('file-loader'),            options: {              name: 'static/media/[name].[hash:8].[ext]',            },          },        ],      },    ],  },  plugins: [    new HtmlWebpackPlugin({      inject: true,      template: paths.appHtml,      chunksSortMode: 'none',    }),    new InterpolateHtmlPlugin(env.raw),    new webpack.DefinePlugin(env.stringified),    new webpack.HotModuleReplacementPlugin(),    new CaseSensitivePathsPlugin(),    new WatchMissingNodeModulesPlugin(paths.appNodeModules),    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),  ],  node: {    dgram: 'empty',    fs: 'empty',    net: 'empty',    tls: 'empty',    child_process: 'empty',  },  performance: {    hints: false,  },  optimization: {    namedModules: true,    nodeEnv: 'development',  },}

在上面配置中,有变动的地方和 HtmlWebpackPlugin 和 react-dev-utils/InterpolateHtmlPlugin 先后顺序,为

了解决下面问题:

Plugin could not be registered at 'html-webpack-plugin-before-html-processing'. Hook was not found.BREAKING CHANGE:There need to exist a hook at 'this.hooks'. To create a compatiblity layer for this hook, hook into 'this._pluginCompat'.

其次关于 test: /\.less/ 有两次,观察两个 loader 的不同,一个 配置中 css-modules 是关闭,一个是开启

的,同时一个 exclude 是去除 node_modules 一个是 include node_modules, 为了解决 css-modules 的开
启会导致 antd 的样式无法导入问题, 具体可以关注 ant-design 的仓库 issue, 搜索 样式无法导入即可。

上面方案灵感来自于 roadhog loaders 配置

package.json

这部分主要包含最近发新版的包,如下:

// package.json{  "name": "dva项目",  "version": "0.1.0",  "private": true,  "dependencies": {    "@babel/polyfill": "^7.0.0",    "antd": "^3.9.2",    "bizcharts": "^3.2.2",    "classnames": "^2.2.6",    "currency.js": "^1.1.4",    "dva": "^2.4.0",    "enquire-js": "^0.2.1",    "fastclick": "^1.0.6",    "immutable": "^3.8.2",    "lodash": "^4.17.11",    "lodash-decorators": "^6.0.0",    "qrcode": "^1.2.2",    "rc-drawer-menu": "^1.1.0",    "rc-trigger": "^2.5.4",    "react": "^16.5.1",    "react-container-query": "^0.11.0",    "react-countup": "^4.0.0-alpha.6",    "react-dnd": "^5.0.0",    "react-dnd-html5-backend": "^5.0.1",    "react-document-title": "^2.0.3",    "react-dom": "^16.5.1",    "react-virtualized": "^9.20.1",    "rollbar": "^2.4.6",    "ua-parser-js": "^0.7.18",    "xlsx": "^0.14.0"  },  "devDependencies": {    "@babel/core": "^7.0.1",    "@babel/plugin-proposal-class-properties": "^7.0.0",    "@babel/plugin-proposal-decorators": "^7.0.0",    "@babel/plugin-proposal-optional-chaining": "^7.0.0",    "@babel/plugin-syntax-dynamic-import": "^7.0.0",    "@babel/preset-env": "^7.0.0",    "@babel/preset-react": "^7.0.0",    "@babel/runtime": "^7.0.0",    "@types/lodash": "^4.14.116",    "@types/react": "^16.4.14",    "@types/react-dom": "^16.0.7",    "autoprefixer": "7.1.6",    "awesome-typescript-loader": "^5.2.1",    "babel-eslint": "7.2.3",    "babel-jest": "20.0.3",    "babel-loader": "^8.0.0-beta.6",    "babel-plugin-import": "^1.8.0",    "case-sensitive-paths-webpack-plugin": "2.1.1",    "chalk": "1.1.3",    "css-loader": "0.28.7",    "dotenv": "4.0.0",    "dotenv-expand": "4.2.0",    "eslint": "4.10.0",    "eslint-config-react-app": "^2.1.0",    "eslint-loader": "1.9.0",    "eslint-plugin-flowtype": "2.39.1",    "eslint-plugin-import": "2.8.0",    "eslint-plugin-jsx-a11y": "5.1.1",    "eslint-plugin-react": "7.4.0",    "extract-text-webpack-plugin": "3.0.2",    "file-loader": "^2.0.0",    "fs-extra": "3.0.1",    "happypack": "^5.0.0",    "hard-source-webpack-plugin": "^0.12.0",    "html-webpack-plugin": "^3.2.0",    "jest": "20.0.4",    "less": "^3.8.1",    "less-loader": "^4.1.0",    "object-assign": "4.1.1",    "postcss-flexbugs-fixes": "3.2.0",    "postcss-loader": "2.0.8",    "promise": "8.0.1",    "raf": "3.4.0",    "react-dev-utils": "^6.0.0-next.a671462c",    "resolve": "1.6.0",    "style-loader": "0.19.0",    "sw-precache-webpack-plugin": "^0.11.5",    "ts-import-plugin": "^1.5.5",    "typescript": "^3.0.3",    "url-loader": "0.6.2",    "webpack": "^4.19.0",    "webpack-cli": "^3.1.0",    "webpack-dev-server": "^3.1.8",    "webpack-manifest-plugin": "^2.0.4",    "whatwg-fetch": "2.0.3"  },  "scripts": {    "dev": "NODE_ENV=development webpack --config config/webpack.config.dev.js --profile",    "start": "node scripts/start.js",    "build": "node scripts/build.js",    "test": "node scripts/test.js --env=jsdom"  }}

.babelrc

不仅将 webpack 从 v3 到 v4 而且,基本把 babel 都升级到最新版,最新版的 babel 都是在 @babel 命名空间

{  "presets": ["@babel/preset-env", "@babel/preset-react"],  "plugins": [    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": true }],    "@babel/plugin-syntax-dynamic-import",    ["@babel/plugin-proposal-decorators", { "legacy": true }],    "@babel/plugin-proposal-class-properties",    "@babel/plugin-proposal-optional-chaining"  ]}

常见问题

WARNING in configurationThe 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

增加 webpack 文件中 mode: 'production' 或者 development

(node:6005) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead    at ModuleScopePlugin.apply (/Users/yes/.../node_modules/react-dev-utils/ModuleScopePlugin.js:21:14)

升级 react-dev-utils 即可

$ yarn add -D react-dev-utils@next

总结

使用 cra 以后, 虽然一开始还是比较慢,但是已经比 roadhog 编译快很多了,而且热编译也很不错,最重要是你能够对项目从配置到具体业务都有充足了解和认识,同时也对 roadhog 学习一波. 用上 webpack4 以后又可以对v4 版本的 Code Splitting, chunk graph and the splitChunks optimization 进行学习了

版本来自:

转载地址:http://ccwza.baihongyu.com/

你可能感兴趣的文章
在使用EF开发时候,遇到 using 语句中使用的类型必须可隐式转换为“System.IDisposable“ 这个问题。...
查看>>
PHP使用DES进行加密和解密
查看>>
Oracle 如何提交手册Cluster Table事务
查看>>
Android Clipboard(复制/剪贴板)
查看>>
BeagleBone Black第八课板:建立Eclipse编程环境
查看>>
在服务器上用Fiddler抓取HTTPS流量
查看>>
文件类似的推理 -- 超级本征值(super feature)
查看>>
XCode的代码块备份
查看>>
iOs 自定义UIView 日历的实现 Swift2.1
查看>>
【XCode7+iOS9】http网路连接请求、MKPinAnnotationView自定义图片和BitCode相关错误--备用...
查看>>
各大公司容器云的技术栈对比
查看>>
记一次eclipse无法启动的排查过程
查看>>
Apache Storm 与 Spark:对实时处理数据,如何选择【翻译】
查看>>
【转】jmeter 进行java request测试
查看>>
读书笔记--MapReduce 适用场景 及 常见应用
查看>>
SignalR在Xamarin Android中的使用
查看>>
你真的会玩SQL吗?实用函数方法汇总
查看>>
走过电竞之路的程序员
查看>>
Eclipse和MyEclipse使用技巧--Eclipse中使用Git-让版本管理更简单
查看>>
[转]响应式表格jQuery插件 – Responsive tables
查看>>