前言:譯者一直使用react,可是前段時間由於facebook的協議問題,公司開始禁止使用react來開發前端項目。(更新到react16的MIT協議也不行)因而,筆者決定將react替換爲preact,這樣就須要在webpack配置中設置alias,可是又不但願使用create-react-app中不可逆的eject。因而找到了這篇教程,簡單翻譯後結合本身的須要進行了修改。分享給有須要的人。css
Create React App提供了一套很是不錯的配置,可以上手即用,而且提供了「eject」功能,讓你可以本身接管全部的配置項。前端
可是,若是當你僅僅是想微調一下Webpack的配置呢?而並非接管全部的配置項。你可能想要增長SASS或者SCSS的支持,或者使用本身定義的.eslintrc文件。(譯者的使用場景是在webpack中增長alias)node
讓咱們開始講解如何操做。react
警告!
首先你要注意: 若是你並不瞭解Webpack的運行機制,或是不喜歡在工程里加入的hacky代碼(少許的),我建議你不要使用這種方式,這是一種高級的技巧。webpack
當Create React App變化時,特別是它使用的react-scripts包變化時,頗有可能致使咱們的代碼須要一些修復。若是官方修改了webpack的結構,或者導出方式,咱們的代碼將出現問題,這時就須要你本身去了解如何修復它們。因此,再強調一次,若是你以爲這種方式有問題,請不要這麼作!(譯者以爲原做者有點誇張了)git
破解Create React App
好了,有了這個可怕的免責聲明,讓咱們來看看如何破解Create React App,若是你想直接去看示例項目的代碼,也是能夠的。在開始以前,確保使用的是最新的react-scripts,做者在編寫的時候是1.0.11。(譯者使用的是1.4.1)github
Create React App的基礎被封裝在「react-scripts」包中,能夠在package.json中的「dependencies」的列表裏瞭解到。web
咱們將使用rewire來建立猴子補丁(運行時動態替換),使得咱們在執行以前對Webpack配置進行定製。npm
下面這個文件是這個項目中最重要的部分。我建議在您的CRA項目中創建一個名爲「scripts」的目錄,並將這些代碼放入scripts/customized-config.js文件中。你能夠任意命名,不過(稍後咱們將用到這個文件名)。json
scripts/customized-config.js
/* 本模塊運行react-scripts裏的腳本 (Create React App) 能夠自定義webpack配置,經過在項目根目錄建立"config-overrides.dev.js" 、 "config-overrides.prod.js" 文件. A config-overrides file should export a single function that takes a config and modifies it as necessary. module.exports = function(webpackConfig) { webpackConfig.module.rules[0].use[0].options.useEslintrc = true; }; */ var rewire = require('rewire'); var proxyquire = require('proxyquire'); switch(process.argv[2]) { // The "start" script is run during development mode case 'start': rewireModule('react-scripts/scripts/start.js', loadCustomizer('../config-overrides.dev')); break; // The "build" script is run to produce a production bundle case 'build': rewireModule('react-scripts/scripts/build.js', loadCustomizer('../config-overrides.prod')); break; // The "test" script runs all the tests with Jest case 'test': // Load customizations from the config-overrides.testing file. // That file should export a single function that takes a config and returns a config let customizer = loadCustomizer('../config-overrides.testing'); proxyquire('react-scripts/scripts/test.js', { // When test.js asks for '../utils/createJestConfig' it will get this instead: '../utils/createJestConfig': (...args) => { // Use the existing createJestConfig function to create a config, then pass // it through the customizer var createJestConfig = require('react-scripts/utils/createJestConfig'); return customizer(createJestConfig(...args)); } }); break; default: console.log('customized-config only supports "start", "build", and "test" options.'); process.exit(-1); } // Attempt to load the given module and return null if it fails. function loadCustomizer(module) { try { return require(module); } catch(e) { if(e.code !== "MODULE_NOT_FOUND") { throw e; } } // If the module doesn't exist, return a // noop that simply returns the config it's given. return config => config; } function rewireModule(modulePath, customizer) { // Load the module with `rewire`, which allows modifying the // script's internal variables. let defaults = rewire(modulePath); // Reach into the module, grab its global 'config' variable, // and pass it through the customizer function. // The customizer should *mutate* the config object, because // react-scripts imports the config as a `const` and we can't // modify that reference. let config = defaults.__get__('config'); customizer(config); }
爲了跑通代碼,你須要安裝一些額外的依賴包:
npm install --save rewire proxyquire
你能夠經過註釋來了解它是如何工做的。最有趣的部分是位於底部的rewireModule方法,它使用rewire庫來查看另外一個文件,並獲取定義在那裏的配置變量的引用。
一旦你完成了這個操做,就能夠爲開發,生產,測試環境編寫用來覆蓋的配置文件。這一部分徹底取決於你——不管你對CRA的Webpack配置作了什麼改動,你均可以直接去作。
這些文件應該直接在CRA文件夾的根目錄下,全部3個文件都是可選的。若是您想要從新配置它們的位置,只需改變上面「loadCustomizer」調用的路徑。只是不要把它們放在「src」中就能夠。
下面是一些開發環境替換配置的例子:
config-overrides.dev.js
const path = require('path'); module.exports = function(config) { // 使用你本身的 ESLint let eslintLoader = config.module.rules[0]; eslintLoader.use[0].options.useEslintrc = true; // Add the SASS loader second-to-last // (last one must remain as the "file-loader") let loaderList = config.module.rules[1].oneOf; loaderList.splice(loaderList.length - 1, 0, { test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] }); }
還須要建立一個config-overrides.prod.js文件具備相同的內容。開發過程當中使用的是dev文件(例如npm start),在構建期間使用prod文件(例如,npm run build)。
爲了讓剛剛的配置生效,你須要安裝SASS loader, 和它的依賴node-sass:
npm install --save sass-loader node-sass
最後,要讓這些新代碼生效,你須要更改package.json,調用這些新的腳本,而不是默認的react-scripts的腳本。要作到這一點,能夠用如下方法替換「start」、「build」和「test」。
package.json
"scripts": { "start": "node scripts/customized-config start", "build": "node scripts/customized-config build", "test": "node scripts/customized-config test --env=jsdom", }
示例項目
一個CRA生成的項目,在github上,點擊這裏.
譯者補充:
1.原文沒有講到默認的配置文件位置,是在node_modules\react-scripts\config\
目錄下的webpack.config
開頭的文件,例如:webpack.config.dev.js
2.替換react爲preact只須要在config-overrides.dev.js
文件中加入:
/* * 替換react爲preact * */ let alias = config.resolve.alias alias["react"] = "preact-compat" alias["react-dom"] = "preact-compat"
相關資料:
preact替換react:https://preactjs.com/guide/sw...