diff --git a/.gitignore b/.gitignore index bd6ef5dc6..66e53c0aa 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,15 @@ # production /build /lib -/src/**/index.js # Readme copy for github pages site /src/_playground/documentation/Home/README.md +#index files +/src/**/index.js + +#size-limit output +/dist + # misc .DS_Store .env.local diff --git a/.size-limit b/.size-limit index b3dc3a69d..611c588f7 100644 --- a/.size-limit +++ b/.size-limit @@ -1,8 +1,7 @@ [ { name: "Fundamental-React Size", - webpack: true, - path: "lib/index.js", - limit: "50 KB" + config: "config/webpack.config.sizeLimit.js", + limit: "400 KB" } ] diff --git a/README.md b/README.md index 33469e711..5638187f3 100644 --- a/README.md +++ b/README.md @@ -25,18 +25,22 @@ You will need to install [Node and Node Package Manager](https://www.npmjs.com/g For an existing react application, follow the steps below: -1. Install `fundamental-react` and `fundamental-styles`. +1. Install `fundamental-react`. ``` - npm install fundamental-styles fundamental-react + npm install fundamental-react ``` -1. Load the `fundamental-styles` styles. If using create-react-app, this will be in `App.css`. +1. As some components are currently packaged together with their respective `scss`, you will need to edit your webpack configuration to handle these files. See [sass-loader](https://github.com/webpack-contrib/sass-loader). - ```scss - @import '~fundamental-styles/dist/fundamental-styles-ie11.min.css'; +1. Load the `fundamental-styles` styles. This is now packaged as a dependency with `fundamental-react`. If using create-react-app, this will be in `App.css`. + + ```css + @import '~fundamental-styles/scss/fundamental-styles-ie11.css'; ``` + > **NOTE:** Once all components are packaged with their respective `scss`, this step will not be needed. + 1. Import components as needed. See [Component Documentation](https://sap.github.io/fundamental-react/) for examples and API details. ```javascript import { Alert } from 'fundamental-react/Alert'; @@ -49,6 +53,7 @@ For an existing react application, follow the steps below: > **NOTE:** Importing from specific component is recommended. Doing so will bring in only the component you are using instead of the whole library, which will reduce your bundle size significantly. + ## Versioning The `fundamental-react` library follows [Semantic Versioning](https://semver.org/). These components strictly adhere to the `[MAJOR].[MINOR].[PATCH]` numbering system (also known as `[BREAKING].[FEATURE].[FIX]`). diff --git a/config/jest/jest.config.js b/config/jest/jest.config.js index 5dc2cdb31..4b93e9ed2 100644 --- a/config/jest/jest.config.js +++ b/config/jest/jest.config.js @@ -1,20 +1,12 @@ -import Adapter from 'enzyme-adapter-react-16'; -import { configure } from 'enzyme'; - -configure({ adapter: new Adapter() }); - -//https://github.com/FezVrasta/popper.js/issues/478 -if (global.document) { - document.createRange = () => ({ - setStart: () => { }, - setEnd: () => { }, - commonAncestorContainer: { - nodeName: 'BODY', - ownerDocument: document - } - }); -} module.exports = { - 'testURL': 'http://localhost/' + 'rootDir': '../../', + 'verbose': true, + 'testURL': 'http://localhost/', + 'testMatch': ['**/*.test.js'], + 'setupFiles': ['./config/jest/setup.js'], + 'moduleFileExtensions': ['js', 'json', 'jsx', 'scss', 'node'], + 'moduleNameMapper': { + '^.+\\.(css|scss)$': 'babel-jest' + } }; diff --git a/config/jest/setup.js b/config/jest/setup.js new file mode 100644 index 000000000..c66c04480 --- /dev/null +++ b/config/jest/setup.js @@ -0,0 +1,16 @@ +import Adapter from 'enzyme-adapter-react-16'; +import { configure } from 'enzyme'; + +configure({ adapter: new Adapter() }); + +//https://github.com/FezVrasta/popper.js/issues/478 +if (global.document) { + document.createRange = () => ({ + setStart: () => { }, + setEnd: () => { }, + commonAncestorContainer: { + nodeName: 'BODY', + ownerDocument: document + } + }); +} diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 70431102c..f22ddd091 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -2,43 +2,41 @@ /* eslint-disable camelcase */ 'use strict'; - -const fs = require('fs'); const path = require('path'); -const resolve = require('resolve'); const webpack = require('webpack'); -const PnpWebpackPlugin = require('pnp-webpack-plugin'); 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 ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); -const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); const getClientEnvironment = require('./env'); const paths = require('./paths'); const ManifestPlugin = require('webpack-manifest-plugin'); -const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt'); -const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); - -// Webpack uses `publicPath` to determine where the app is being served from. -// In development, we always serve from the root. This makes config easier. const publicPath = '/'; -// `publicUrl` is just like `publicPath`, but we will provide it to our app -// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. -// Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz. const publicUrl = ''; -// Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); -// Check if TypeScript is setup -const useTypeScript = fs.existsSync(paths.appTsConfig); - // style files regexes const cssRegex = /\.css$/; -const cssModuleRegex = /\.module\.css$/; const sassRegex = /\.(scss|sass)$/; -const sassModuleRegex = /\.module\.(scss|sass)$/; + + +const getLintingRule = () => { + return process.env.FUNDAMENTAL_REACT_PLAYGROUND ? + {} : { + test: /\.(js|mjs|jsx)$/, + enforce: 'pre', + use: [ + { + options: { + formatter: require.resolve('react-dev-utils/eslintFormatter'), + eslintPath: require.resolve('eslint') + + }, + loader: require.resolve('eslint-loader') + } + ], + include: paths.appSrc + }; +}; // common function to get style loaders const getStyleLoaders = (cssOptions, preProcessor) => { @@ -49,21 +47,24 @@ const getStyleLoaders = (cssOptions, preProcessor) => { options: cssOptions }, { - // Options for PostCSS as we reference these options twice - // Adds vendor prefixing based on your specified browser support in - // package.json loader: require.resolve('postcss-loader'), options: { - // Necessary for external CSS imports to work - // https://github.com/facebook/create-react-app/issues/2677 ident: 'postcss', + inline: false, + annotations: false, + sourcesContent: true, plugins: () => [ require('postcss-flexbugs-fixes'), require('postcss-preset-env')({ autoprefixer: { - flexbox: 'no-2009' + flexbox: 'no-2009', + cascade: true }, stage: 3 + }), + require('postcss-clean')({ + format: 'beautify', + level: 1 }) ] } @@ -75,139 +76,38 @@ const getStyleLoaders = (cssOptions, preProcessor) => { return loaders; }; -const getLintingRule = () => { - return process.env.FUNDAMENTAL_REACT_PLAYGROUND ? - {} : { - test: /\.(js|mjs|jsx)$/, - enforce: 'pre', - use: [ - { - options: { - formatter: require.resolve('react-dev-utils/eslintFormatter'), - eslintPath: require.resolve('eslint') - - }, - loader: require.resolve('eslint-loader') - } - ], - include: paths.appSrc - }; -}; - -// This is the development configuration. -// It is focused on developer experience and fast rebuilds. -// The production configuration is different and lives in a separate file. module.exports = { mode: 'development', - // You may want 'eval' instead if you prefer to see the compiled output in DevTools. - // See the discussion in https://github.com/facebook/create-react-app/issues/343 devtool: 'cheap-module-source-map', - // These are the "entry points" to our application. - // This means they will be the "root" imports that are included in JS bundle. entry: [ - // Include an alternative client for WebpackDevServer. A client's job is to - // connect to WebpackDevServer by a socket and get notified about changes. - // When you save a file, the client will either apply hot updates (in case - // of CSS changes), or refresh the page (in case of JS changes). When you - // make a syntax error, this client will display a syntax error overlay. - // Note: instead of the default WebpackDevServer client, we use a custom one - // to bring better experience for Create React App users. You can replace - // the line below with these two lines if you prefer the stock client: - // require.resolve('webpack-dev-server/client') + '?/', - // require.resolve('webpack/hot/dev-server'), require.resolve('react-dev-utils/webpackHotDevClient'), - // Finally, this is your app's code: paths.appIndexJs - // We include the app code last so that if there is a runtime error during - // initialization, it doesn't blow up the WebpackDevServer client, and - // changing JS code would still trigger a refresh. ], output: { - // Add /* filename */ comments to generated require()s in the output. pathinfo: true, - // This does not produce a real file. It's just the virtual path that is - // served by WebpackDevServer in development. This is the JS bundle - // containing code from all our entry points, and the Webpack runtime. filename: 'static/js/bundle.js', - // There are also additional JS chunk files if you use code splitting. chunkFilename: 'static/js/[name].chunk.js', - // This is the URL that app is served from. We use "/" in development. publicPath: publicPath, - // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/') }, optimization: { - // Automatically split vendor and commons - // https://twitter.com/wSokra/status/969633336732905474 - // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 splitChunks: { chunks: 'all', name: false }, - // Keep the runtime chunk seperated to enable long term caching - // https://twitter.com/wSokra/status/969679223278505985 runtimeChunk: true }, resolve: { - // This allows you to set a fallback for where Webpack should look for modules. - // We placed these paths second because we want `node_modules` to "win" - // if there are any conflicts. This matches Node resolution mechanism. - // https://github.com/facebook/create-react-app/issues/253 - modules: ['node_modules'].concat( - // It is guaranteed to exist because we tweak it in `env.js` - process.env.NODE_PATH.split(path.delimiter).filter(Boolean) - ), - // These are the reasonable defaults supported by the Node ecosystem. - // We also include JSX as a common component filename extension to support - // some tools, although we do not recommend using it, see: - // https://github.com/facebook/create-react-app/issues/290 - // `web` extension prefixes have been added for better support - // for React Native Web. - extensions: paths.moduleFileExtensions - .map(ext => `.${ext}`) - .filter(ext => useTypeScript || !ext.includes('ts')), - alias: { - // Support React Native Web - // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ - 'react-native': 'react-native-web' - }, - plugins: [ - // Adds support for installing with Plug'n'Play, leading to faster installs and adding - // guards against forgotten dependencies and such. - PnpWebpackPlugin, - // Prevents users from importing files from outside of src/ (or node_modules/). - // This often causes confusion because we only process files within src/ with babel. - // To fix this, we prevent you from importing files out of src/ -- if you'd like to, - // please link the files into your node_modules/ and let module-resolution kick in. - // Make sure your source files are compiled, as they will not be processed in any way. - new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]) - ] - }, - resolveLoader: { - plugins: [ - // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders - // from the current package. - PnpWebpackPlugin.moduleLoader(module) - ] + extensions: ['.js', '.jsx', '.json', '.es6'], + symlinks: false }, module: { strictExportPresence: true, rules: [ - // Disable require.ensure as it's not a standard language feature. - { parser: { requireEnsure: false } }, - - // First, run the linter. - // It's important to do this before Babel processes the JS. getLintingRule(), { - // "oneOf" will traverse all following loaders until one will - // match the requirements. When no loader matches it will fall - // back to the "file" loader at the end of the loader list. oneOf: [ - // "url" loader works like "file" loader except that it embeds assets - // smaller than specified limit in bytes as data URLs to avoid requests. - // A missing `test` is equivalent to a match. { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve('url-loader'), @@ -216,119 +116,30 @@ module.exports = { name: 'static/media/[name].[hash:8].[ext]' } }, - // Process application JS with Babel. - // The preset includes JSX, Flow, and some ESnext features. - { - test: /\.(js|mjs|jsx|ts|tsx)$/, - include: paths.appSrc, - loader: require.resolve('babel-loader'), - options: { - customize: require.resolve( - 'babel-preset-react-app/webpack-overrides' - ), - plugins: [ - [ - require.resolve('babel-plugin-named-asset-import'), - { - loaderMap: { - svg: { - ReactComponent: '@svgr/webpack?-prettier,-svgo![path]' - } - } - } - ] - ], - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in ./node_modules/.cache/babel-loader/ - // directory for faster rebuilds. - cacheDirectory: true, - // Don't waste time on Gzipping the cache - cacheCompression: false - } - }, - // Process any JS outside of the app with Babel. - // Unlike the application JS, we only compile the standard ES features. { - test: /\.(js|mjs)$/, - exclude: /@babel(?:\/|\\{1,2})runtime/, - loader: require.resolve('babel-loader'), - options: { - babelrc: false, - configFile: false, - compact: false, - presets: [ - [ - require.resolve('babel-preset-react-app/dependencies'), - { helpers: true } + test: /\.(js|jsx)$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: [ + '@babel/preset-env', + '@babel/preset-react' ] - ], - cacheDirectory: true, - // Don't waste time on Gzipping the cache - cacheCompression: false, - - // If an error happens in a package, it's possible to be - // because it was compiled. Thus, we don't want the browser - // debugger to show the original code. Instead, the code - // being evaluated would be much more helpful. - sourceMaps: false + } } }, - // "postcss" loader applies autoprefixer to our CSS. - // "css" loader resolves paths in CSS and adds assets as dependencies. - // "style" loader turns CSS into JS modules that inject