Commit aa92f3d6 by baiguangyao

路由以及底部选中状态优化

parent 378fbb62
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
const theme = require('../package.json').theme;
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = 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_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
{
loader: require.resolve('sass-loader'),
options: cssOptions,
},
{
loader: require.resolve('style-loader'),
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',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && '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'),
isEnvDevelopment &&
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.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// 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 separated 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),
],
},
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.
{
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,
},
{
// "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'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, 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?-svgo,+ref![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,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// 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 },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// 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 <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader', options: { modifyVars: theme } },
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
module: 'empty',
dgram: 'empty',
dns: 'mock',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
const theme = require('../package.json').theme;
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = 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_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
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',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && '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'),
isEnvDevelopment &&
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.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// 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 separated 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),
],
},
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.
{
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,
},
{
// "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'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, 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?-svgo,+ref![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,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// 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 },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// 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 <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader', options: { modifyVars: theme } },
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
module: 'empty',
dgram: 'empty',
dns: 'mock',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
const theme = require('../package.json').theme;
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = 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_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
test: /\.scss$/,
include: path.resolve(__dirname, 'src/js'),
loaders: [
'style',
'css?modules&sourceMap&importLoaders=1&localIdentName=[local]___[hash:base64:5]',
'postcss?parser=postcss-scss'
]
},
{
test: /\.scss$/,
include: path.resolve(__dirname, 'src/styles'),
loader: 'style!css!postcss?parser=postcss-scss'
},
{
loader: require.resolve('css-loader'),
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',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && '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'),
isEnvDevelopment &&
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.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// 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 separated 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),
],
},
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.
{
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,
},
{
// "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'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, 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?-svgo,+ref![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,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// 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 },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// 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 <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader', options: { modifyVars: theme } },
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
module: 'empty',
dgram: 'empty',
dns: 'mock',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
const theme = require('../package.json').theme;
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = 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_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
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',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && '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'),
isEnvDevelopment &&
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.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// 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 separated 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),
],
},
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.
{
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,
},
{
// "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'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, 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?-svgo,+ref![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,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// 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 },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// 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 <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader', options: { modifyVars: theme } },
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
module: 'empty',
dgram: 'empty',
dns: 'mock',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
const theme = require('../package.json').theme;
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
// In development, we always serve from the root. This makes config easier.
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = 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_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
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',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: isEnvProduction && shouldUseSourceMap,
},
},
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
});
}
return loaders;
};
return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
// Stop compilation early in production
bail: isEnvProduction,
devtool: isEnvProduction
? shouldUseSourceMap
? 'source-map'
: false
: isEnvDevelopment && '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'),
isEnvDevelopment &&
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.
].filter(Boolean),
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
// Add /* filename */ comments to generated require()s in the output.
pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
optimization: {
minimize: isEnvProduction,
minimizer: [
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// we want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap,
}),
// This is only used in production mode
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: shouldUseSourceMap
? {
// `inline: false` forces the sourcemap to be output into a
// separate file
inline: false,
// `annotation: true` appends the sourceMappingURL to the end of
// the css file, helping the browser find the sourcemap
annotation: true,
}
: false,
},
}),
],
// 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 separated 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),
],
},
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.
{
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,
},
{
// "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'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, 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?-svgo,+ref![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,
cacheCompression: isEnvProduction,
compact: isEnvProduction,
},
},
// 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 },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// 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 <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader', options: { modifyVars: theme } },
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment &&
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
watch: paths.appSrc,
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
module: 'empty',
dgram: 'empty',
dns: 'mock',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
};
import React, { Component } from 'react'
import { Link } from 'react-router'
import styles from './index.scss'
export default class NavLink extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
.root {
flex: auto;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
line-height: 1;
color: #666;
&:hover {
color: #1abc9c;
}
}
.ico {
font-size: 0.42rem;
display: block;
margin-bottom: 0.1rem;
}
.text {
display: block;
line-height: 1;
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLink extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLink extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
.root {
flex: auto;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
line-height: 1;
color: #666;
&:hover {
color: #0099ff;
}
}
.ico {
font-size: 0.42rem;
display: block;
margin-bottom: 0.1rem;
}
.text {
display: block;
line-height: 1;
}
\ No newline at end of file
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom';
import styles from './index.scss'
export default class NavLink extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName } = this.props;
return (
<Link
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<Link
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</Link>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import NavLink from './NavLink'
import styles from './index.scss'
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
onlyActiveOnIndex
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
.root {
background-color: #f5f5f5;
height: 1rem;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #1abc9c;
&:hover, &:active {
color: #1abc9c;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
import React, { Component } from 'react'
import NavLink from './NavLink'
import styles from './index.scss'
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import NavLink from './NavLink'
import styles from './index.scss'
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName={styles.navOne}
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName={styles.navOne}
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
// activeClassName={styles.navOne}
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={'css'}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={'css'}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
// active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
// active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
// active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
// active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
.root {
background-color: #f5f5f5;
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #1abc9c;
&:hover, &:active {
color: #1abc9c;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
.root {
background-color: #f5f5f5;
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #1abc9c;
&:hover, &:active {
color: #1abc9c;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
.root {
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #1abc9c;
&:hover, &:active {
color: #1abc9c;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
exact
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<Redirect from="/" exact to="/index" />
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<Redirect from="/" exact to="/index" />
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
activeClassName="active"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
activeClassName="active"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
activeClassName="active"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
.root {
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #09f;
&:hover, &:active {
color: #1abc9c;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
.root {
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #09f;
&:hover, &:active {
color: #09f;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink exact to='/' pathUrl="/index"></NavLink>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
className="active"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { PureComponent } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends PureComponent {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
exact
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
activeClassName="active"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/index"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
exact
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react'
import NavLink from './NavLink'
import styles from './index.scss'
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '1.2rem' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
onlyActiveOnIndex
/>
<NavLink
pathUrl="/shop"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="好店"
/>
<NavLink
pathUrl="/coupon"
icoName="i-youhui42un"
active={styles.navThree}
linkName="优惠"
/>
<NavLink
pathUrl="/tour"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="周边"
/>
<NavLink
pathUrl="/user"
icoName="i-wode42un"
active={styles.navFive}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
// 底部路由
export { default as Nav } from './Nav'
\ No newline at end of file
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router';
// import { Provider } from 'react-redux';
import './styles/index.scss';
// import App from './App';
ReactDOM.render(
<Router />,
document.getElementById('root'));
\ No newline at end of file
...@@ -7,6 +7,8 @@ import Classify from './components/classify'; ...@@ -7,6 +7,8 @@ import Classify from './components/classify';
import Study from './components/study'; import Study from './components/study';
import My from './components/my'; import My from './components/my';
import './styles/index.scss'
const main = () => ( const main = () => (
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
......
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const main = () => (
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
)
export default main;
\ No newline at end of file
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const main = () => (
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
)
export default main;
\ No newline at end of file
import React from 'react'
import { TabBar } from 'antd-mobile'
import { Link } from 'react-router-dom';
import { Nav} from './common'
class menu extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.onPress = this.onPress.bind(this);
}
onPress(item) {
this.setState({ selected: item })
}
render(match) {
let { selected = 'index' } = this.state;
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<TabBar>
<TabBar.Item
title="首页"
key="home"
icon={<Link to='/index'><i className='iconfont icon-youhuijuan tabbarIcon' >121212</i> </Link>}
selectedIcon={<Link to='/index'><i className='iconfont icon-youhuijuan selectedTabbarIcon' ></i> </Link>}
selected={selected === 'index' ? true : false}
onPress={() => { this.onPress('index') }}
/>
<TabBar.Item
title="分类"
key="classify"
icon={<Link to='/classify'><i className='iconfont icon-zhangdan-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/classify'><i className='iconfont icon-zhangdan-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'classify' ? true : false}
onPress={() => { this.onPress('classify') }}
/>
<TabBar.Item
title="学习"
key="study"
icon={<Link to='/study'><i className='iconfont icon-zhangdan-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/study'><i className='iconfont icon-zhangdan-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'study' ? true : false}
onPress={() => { this.onPress('study') }}
/>
<TabBar.Item
title="我的"
key="my"
icon={<Link to='/my'><i className='iconfont icon-yonghu-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/my'><i className='iconfont icon-yonghu-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'my' ? true : false}
onPress={() => { this.onPress('my') }}
/>
</TabBar>
</div>
)
}
}
export default menu;
import React from 'react'
import { TabBar } from 'antd-mobile'
import { Link } from 'react-router-dom';
import { Nav} from './common'
class menu extends React.Component {
render(match) {
let { selected = 'index' } = this.state;
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
</div>
)
}
}
export default menu;
import React from 'react'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { TabBar } from 'antd-mobile'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
// import { TabBar } from 'antd-mobile'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
// import { TabBar } from 'antd-mobile'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
const { HashRouter, Route, NavLink } = 'react-router-dom';
// import { TabBar } from 'antd-mobile'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
// import { TabBar } from 'antd-mobile'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { Nav} from './common'
class menu extends React.Component {
render(match) {
return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<Nav />
</div>
)
}
}
export default menu;
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Main from './main'
const router = () => (
<Router>
<Route path='/' exact component={Main}>
</Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Main from './main'
const router = () => (
<Route path='/' exact component={Main}>
</Route>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Main from './main'
const router = () => (
<Router>
<Route path='/' exact component={Main}>
</Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
import Main from './main'
const router = () => (
<Router>
<Route path='/' exact component={Main}>
</Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
// import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
import Main from './main'
const router = () => (
<Router>
<Route path='/' exact component={Main}>
</Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Main from './main'
const router = () => (
<Router>
<Route path='/' exact component={Main}>
</Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom";
import Main from './main'
const router = () => (
<Router>
<Route path='/' component={Main}>
</Route>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
import Main from './main'
const router = () => (
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' exact component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' exact component={Index}></Route>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
// import { HashRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
// import Main from './main'
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/' component={Index}></Route>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route path='/index' component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
<div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}>
<div>
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
</div>
<Menu />
</div>
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
{/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
{/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
const router = () => (
<Router>
{/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import './styles/index.scss';
const router = () => (
<Router>
{/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router>
)
export default router;
\ No newline at end of file
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
const router = () => (
<Router>
{/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router>
)
export default router;
\ No newline at end of file
// 使用建议
// --------------------------------------------------
// CSS Modules 是对现有的 CSS 做减法。为了追求简单可控,建议遵循如下原则:
// ·不使用选择器(id,伪类,标签等),只使用class名来定义样式
// ·不层叠多个class,只使用一个class把所有样式定义好
// ·所有样式通过 composes 组合来实现复用
// ·不嵌套
// --------------------------------------------------
// 公有样式引入mixins的目的是为了方便默认设置若干常用的样式
// 公有样式不可以使用composes
@import "./mixins.scss";
// 颜色设置
$border-color: #e9e9e9; //边框颜色
$body-color: #333; //设置通用的字体颜色
$body-bg: #f2f2f2; //设置通用的 body 背景色
$link-color: #333; //设置通用的链接颜色
$link-visited: #333; //设置链接访问后的颜色
$main-color: #1BBC9B; //主体颜色
// 字体
$font-family-zh: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
$font-family-en: Arial, sans-serif !default;
// 盒子模型
$box-model: border-box !default;
// z-index
$z-50: 50;
$z-100: 100;
$z-150: 150;
$z-200: 200;
$z-250: 250;
$z-max: 999999; //为了应付某些插件z-index 值过高的问题
// 全局设置
// --------------------------------------------------
//
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
border: 0 none;
font-size: inherit;
color: inherit;
margin: 0;
padding: 0;
vertical-align: baseline;
/* 在X5新内核Blink中,在排版页面的时候,会主动对字体进行放大,会检测页面中的主字体,当某一块字体在我们的判定规则中,认为字号较小,并且是页面中的主要字体,就会采取主动放大的操作。然而这不是我们想要的,可以采取给最大高度解决 */
max-height: 100000px;
}
h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
em, strong {
font-style: normal;
}
ul, ol, li {
list-style: none;
}
// 全局盒子模型设置
* {
box-sizing: $box-model;
}
*:before,
*:after {
box-sizing: $box-model;
}
// -webkit-tap-highlight-color 是一个 不规范的属性,它没有出现在 CSS 规范草案中。
// 当用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色。
html {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
font-family: $font-family-zh;
line-height: 1.5;
color: $body-color;
background-color: $body-bg;
font-size: 0.24rem;
}
// Links
a {
text-decoration: none;
outline: none;
&:hover,
&:link,
&:focus {
text-decoration: none;
}
&:visited {
}
}
// 暂时放置样式,后期需处理
.homeImg {
display: block;
width: 100%;
}
// 字体颜色
.main-color {
color: $main-color;
}
.color333 {
color: #333
}
.color666 {
color: #666
}
.color999 {
color: #999
}
// 背景颜色
.bg-white { background-color: #fff }
// 间隔
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt50 {
padding-top: 50px;
}
.pt60 {
padding-top: 60px;
}
.plr20 {
padding-left: 0.2rem;
padding-right: 0.2rem;
}
// 请保证你的设计稿为750px宽,如果有其余字体大小,请在私有样式中设置
.font-20 {font-size: 0.2rem;}
.font-24 {font-size: 0.24rem;}
.font-26 {font-size: 0.26rem;}
.font-28 {font-size: 0.28rem;}
.font-30 {font-size: 0.3rem;}
.font-32 {font-size: 0.32rem;}
.font-34 {font-size: 0.34rem;}
.font-36 {font-size: 0.36rem;}
.font-38 {font-size: 0.38rem;}
.font-40 {font-size: 0.4rem;}
// 设置block
.block {
display: block;
}
.show {
display: inherit;
}
.hide {
display: none;
}
// 最外层页面设置
.box {
max-width: 10rem;
margin-left: auto;
margin-right: auto;
}
// 半透明弹层
.alert-bg {
position: fixed;
z-index: $z-50;
width: 100%;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
display: none; //注意:默认隐藏!!
}
.alpha-bg {
position: fixed;
z-index: 100;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
}
// 布局相关
// 水平
.hor {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
// 水平居中
.hor-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
// 垂直居中
.ver-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
// 子元素内联垂直居中
.center-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 子元素块联水平垂直居中
.center-center-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 两边对齐
.space-between {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
// last-no-border
.last-no-border:last-child {
border: none;
background: none;
}
// 图片设置
img {
max-width: 100%;
}
.img-responsive {
display: block;
width: 100%;
}
// 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题
.home-swipe {
height: 40.625vw;
max-height: 406.25px;
}
// 文本控制类
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
// 字符溢出隐藏
.text-overflow-1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 字符超出一行溢出隐藏
.text-overflow-one {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
// 字符超出两行溢出隐藏
.text-overflow-2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 字符超出三行溢出隐藏
.text-overflow-3 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
// 浮动控制
.cf {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.fl {
float: left;
}
.fr {
float: right;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.z-150 {
z-index: 150;
}
.z-200 {
z-index: 200;
}
.z-250 {
z-index: 250;
}
.z-max {
z-index: 999999;
}
.overflow-h {
overflow: hidden;
}
// 元素绝对定位的垂直水平居中
.absolute-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// flex 参考指南。http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
// 任何一个容器都可以指定 flex 布局
// .box-example { display: flex }
// 行内元素也可以使用 flex 布局
// .box-example { display: inline-flex; }
// 以下6个属性设置在容器上
// 1. flex-direction --> 子项目排列的方向
// row 默认,水平从左到右
// row-reverse 水平从右到左
// column 从上到下
// column-reverse 从下到上
// 2. flex-wrap 默认情况下,子项目都排在一条线上,而此属性解决的是,如果一条线排不下,子项目如何换行
// nowrap 默认,不换行
// wrap 换行,第一行在上方
// wrap-reverse 换行,第一行在下方
// 3. flex-flow 是 flex-direction 和 flex-wrap 的简写形式,默认值为 row nowrap
// 4. justify-content 定义了子项目在主轴上的对齐方式
// flex-start 默认值,左对齐
// flex-end 右对齐
// center 居中
// space-between 两端对齐,子项目之间的间隔相等
// space-around 每个子项目两侧的间隔相等。所以,子项目之间的间隔比子项目与父容器边界的间隔大一倍
// 5. align-items 定义子项目在交叉轴上如何对齐。
// flex-start 交叉轴的起点对齐
// flex-end 交叉轴的终点对齐
// center 交叉轴的中点对齐
// baseline 子项目的第一行文字的基线对齐
// stretch 默认值,如果子项目未设置高度或设为auto,将占满整个容器的高度
// 6. align-content 定义了多根轴线的对齐方式,如果子项目只有一根轴线,则该属性无效。
// flex-start 与交叉轴的起点对齐。
// flex-end 与交叉轴的终点对齐
// center 与交叉轴的中点对齐
// space-between 与交叉轴两端对齐,轴线之间的间隔平均分布。
// space-around 每根轴线两侧的间隔都相等,所以轴线之间的间隔比轴线与边框的间隔大一倍
// stretch 默认值,轴线占满整个交叉轴
// 以下6个属性设置在子项目上。
// 1. order 定义子项目的排列顺序,数值越小,排位越靠前。默认值为0.
// 2. flex-grow 定义子项目放大比例,默认为0,即如果存在剩余空间,也不放大。
// 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。
// 如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
// 3. flex-shrink 定义了子项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
// 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。
// 如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
// 4. flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
// 浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
// 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
// 5. flex 该属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
// 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
// 建议优先使用这个 flex 属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
// align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。
// 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
// 该属性可能取6个值,除了 auto ,其他都与 align-items 属性完全一致。
// ------------------------------------------------------------
// radio 样式重写
input[type="radio"] {
position: relative;
vertical-align: middle;
width: 0.36rem;
height: 0.36rem;
-webkit-appearance: none !important;
-moz-appearance: none;
border: none;
background: none;
outline: none;
}
input[type="radio"]:before {
position: absolute;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
z-index: 100;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:after {
position: absolute;
z-index: 50;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:before {
position: absolute;
z-index: 100;
content: '';
display: block;
width: 0.18rem;
height: 0.18rem;
left: 0.09rem;
top: 0.09rem;
background: #1abc9c;
border-radius: 50%;
border: none;
}
\ No newline at end of file
// 使用建议
// --------------------------------------------------
// CSS Modules 是对现有的 CSS 做减法。为了追求简单可控,建议遵循如下原则:
// ·不使用选择器(id,伪类,标签等),只使用class名来定义样式
// ·不层叠多个class,只使用一个class把所有样式定义好
// ·所有样式通过 composes 组合来实现复用
// ·不嵌套
// --------------------------------------------------
// 公有样式引入mixins的目的是为了方便默认设置若干常用的样式
// 公有样式不可以使用composes
@import "./mixins.scss";
// 颜色设置
$border-color: #e9e9e9; //边框颜色
$body-color: #333; //设置通用的字体颜色
$body-bg: #f2f2f2; //设置通用的 body 背景色
$link-color: #333; //设置通用的链接颜色
$link-visited: #333; //设置链接访问后的颜色
$main-color: #1BBC9B; //主体颜色
// 字体
$font-family-zh: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
$font-family-en: Arial, sans-serif !default;
// 盒子模型
$box-model: border-box !default;
// z-index
$z-50: 50;
$z-100: 100;
$z-150: 150;
$z-200: 200;
$z-250: 250;
$z-max: 999999; //为了应付某些插件z-index 值过高的问题
// 全局设置
// --------------------------------------------------
//
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
border: 0 none;
font-size: inherit;
color: inherit;
margin: 0;
padding: 0;
vertical-align: baseline;
/* 在X5新内核Blink中,在排版页面的时候,会主动对字体进行放大,会检测页面中的主字体,当某一块字体在我们的判定规则中,认为字号较小,并且是页面中的主要字体,就会采取主动放大的操作。然而这不是我们想要的,可以采取给最大高度解决 */
max-height: 100000px;
}
h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
em, strong {
font-style: normal;
}
ul, ol, li {
list-style: none;
}
// 全局盒子模型设置
* {
box-sizing: $box-model;
}
*:before,
*:after {
box-sizing: $box-model;
}
// -webkit-tap-highlight-color 是一个 不规范的属性,它没有出现在 CSS 规范草案中。
// 当用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色。
html {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
font-family: $font-family-zh;
line-height: 1.5;
color: $body-color;
background-color: $body-bg;
font-size: 0.24rem;
}
// Links
a {
text-decoration: none;
outline: none;
&:hover,
&:link,
&:focus {
text-decoration: none;
}
&:visited {
}
}
// 暂时放置样式,后期需处理
.homeImg {
display: block;
width: 100%;
}
// 字体颜色
.main-color {
color: $main-color;
}
.color333 {
color: #333
}
.color666 {
color: #666
}
.color999 {
color: #999
}
// 背景颜色
.bg-white { background-color: #fff }
// 间隔
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt50 {
padding-top: 50px;
}
.pt60 {
padding-top: 60px;
}
.plr20 {
padding-left: 0.2rem;
padding-right: 0.2rem;
}
// 请保证你的设计稿为750px宽,如果有其余字体大小,请在私有样式中设置
.font-20 {font-size: 0.2rem;}
.font-24 {font-size: 0.24rem;}
.font-26 {font-size: 0.26rem;}
.font-28 {font-size: 0.28rem;}
.font-30 {font-size: 0.3rem;}
.font-32 {font-size: 0.32rem;}
.font-34 {font-size: 0.34rem;}
.font-36 {font-size: 0.36rem;}
.font-38 {font-size: 0.38rem;}
.font-40 {font-size: 0.4rem;}
// 设置block
.block {
display: block;
}
.show {
display: inherit;
}
.hide {
display: none;
}
// 最外层页面设置
.box {
max-width: 10rem;
margin-left: auto;
margin-right: auto;
}
// 半透明弹层
.alert-bg {
position: fixed;
z-index: $z-50;
width: 100%;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
display: none; //注意:默认隐藏!!
}
.alpha-bg {
position: fixed;
z-index: 100;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
}
// 布局相关
// 水平
.hor {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
// 水平居中
.hor-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
// 垂直居中
.ver-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
// 子元素内联垂直居中
.center-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 子元素块联水平垂直居中
.center-center-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 两边对齐
.space-between {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
// last-no-border
.last-no-border:last-child {
border: none;
background: none;
}
// 图片设置
img {
max-width: 100%;
}
.img-responsive {
display: block;
width: 100%;
}
// 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题
.home-swipe {
height: 40.625vw;
max-height: 406.25px;
}
// 文本控制类
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
// 字符溢出隐藏
.text-overflow-1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 字符超出一行溢出隐藏
.text-overflow-one {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
// 字符超出两行溢出隐藏
.text-overflow-2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 字符超出三行溢出隐藏
.text-overflow-3 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
// 浮动控制
.cf {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.fl {
float: left;
}
.fr {
float: right;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.z-150 {
z-index: 150;
}
.z-200 {
z-index: 200;
}
.z-250 {
z-index: 250;
}
.z-max {
z-index: 999999;
}
.overflow-h {
overflow: hidden;
}
// 元素绝对定位的垂直水平居中
.absolute-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// radio 样式重写
input[type="radio"] {
position: relative;
vertical-align: middle;
width: 0.36rem;
height: 0.36rem;
-webkit-appearance: none !important;
-moz-appearance: none;
border: none;
background: none;
outline: none;
}
input[type="radio"]:before {
position: absolute;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
z-index: 100;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:after {
position: absolute;
z-index: 50;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:before {
position: absolute;
z-index: 100;
content: '';
display: block;
width: 0.18rem;
height: 0.18rem;
left: 0.09rem;
top: 0.09rem;
background: #1abc9c;
border-radius: 50%;
border: none;
}
\ No newline at end of file
// 使用建议
// --------------------------------------------------
// CSS Modules 是对现有的 CSS 做减法。为了追求简单可控,建议遵循如下原则:
// ·不使用选择器(id,伪类,标签等),只使用class名来定义样式
// ·不层叠多个class,只使用一个class把所有样式定义好
// ·所有样式通过 composes 组合来实现复用
// ·不嵌套
// --------------------------------------------------
// 公有样式引入mixins的目的是为了方便默认设置若干常用的样式
// 公有样式不可以使用composes
// @import "./mixins.scss";
// 颜色设置
$border-color: #e9e9e9; //边框颜色
$body-color: #333; //设置通用的字体颜色
$body-bg: #f2f2f2; //设置通用的 body 背景色
$link-color: #333; //设置通用的链接颜色
$link-visited: #333; //设置链接访问后的颜色
$main-color: #1BBC9B; //主体颜色
// 字体
$font-family-zh: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
$font-family-en: Arial, sans-serif !default;
// 盒子模型
$box-model: border-box !default;
// z-index
$z-50: 50;
$z-100: 100;
$z-150: 150;
$z-200: 200;
$z-250: 250;
$z-max: 999999; //为了应付某些插件z-index 值过高的问题
// 全局设置
// --------------------------------------------------
//
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
border: 0 none;
font-size: inherit;
color: inherit;
margin: 0;
padding: 0;
vertical-align: baseline;
/* 在X5新内核Blink中,在排版页面的时候,会主动对字体进行放大,会检测页面中的主字体,当某一块字体在我们的判定规则中,认为字号较小,并且是页面中的主要字体,就会采取主动放大的操作。然而这不是我们想要的,可以采取给最大高度解决 */
max-height: 100000px;
}
h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
em, strong {
font-style: normal;
}
ul, ol, li {
list-style: none;
}
// 全局盒子模型设置
* {
box-sizing: $box-model;
}
*:before,
*:after {
box-sizing: $box-model;
}
// -webkit-tap-highlight-color 是一个 不规范的属性,它没有出现在 CSS 规范草案中。
// 当用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色。
html {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
font-family: $font-family-zh;
line-height: 1.5;
color: $body-color;
background-color: $body-bg;
font-size: 0.24rem;
}
// Links
a {
text-decoration: none;
outline: none;
&:hover,
&:link,
&:focus {
text-decoration: none;
}
&:visited {
}
}
// 暂时放置样式,后期需处理
.homeImg {
display: block;
width: 100%;
}
// 字体颜色
.main-color {
color: $main-color;
}
.color333 {
color: #333
}
.color666 {
color: #666
}
.color999 {
color: #999
}
// 背景颜色
.bg-white { background-color: #fff }
// 间隔
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt50 {
padding-top: 50px;
}
.pt60 {
padding-top: 60px;
}
.plr20 {
padding-left: 0.2rem;
padding-right: 0.2rem;
}
// 请保证你的设计稿为750px宽,如果有其余字体大小,请在私有样式中设置
.font-20 {font-size: 0.2rem;}
.font-24 {font-size: 0.24rem;}
.font-26 {font-size: 0.26rem;}
.font-28 {font-size: 0.28rem;}
.font-30 {font-size: 0.3rem;}
.font-32 {font-size: 0.32rem;}
.font-34 {font-size: 0.34rem;}
.font-36 {font-size: 0.36rem;}
.font-38 {font-size: 0.38rem;}
.font-40 {font-size: 0.4rem;}
// 设置block
.block {
display: block;
}
.show {
display: inherit;
}
.hide {
display: none;
}
// 最外层页面设置
.box {
max-width: 10rem;
margin-left: auto;
margin-right: auto;
}
// 半透明弹层
.alert-bg {
position: fixed;
z-index: $z-50;
width: 100%;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
display: none; //注意:默认隐藏!!
}
.alpha-bg {
position: fixed;
z-index: 100;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
}
// 布局相关
// 水平
.hor {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
// 水平居中
.hor-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
// 垂直居中
.ver-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
// 子元素内联垂直居中
.center-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 子元素块联水平垂直居中
.center-center-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 两边对齐
.space-between {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
// last-no-border
.last-no-border:last-child {
border: none;
background: none;
}
// 图片设置
img {
max-width: 100%;
}
.img-responsive {
display: block;
width: 100%;
}
// 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题
.home-swipe {
height: 40.625vw;
max-height: 406.25px;
}
// 文本控制类
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
// 字符溢出隐藏
.text-overflow-1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 字符超出一行溢出隐藏
.text-overflow-one {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
// 字符超出两行溢出隐藏
.text-overflow-2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 字符超出三行溢出隐藏
.text-overflow-3 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
// 浮动控制
.cf {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.fl {
float: left;
}
.fr {
float: right;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.z-150 {
z-index: 150;
}
.z-200 {
z-index: 200;
}
.z-250 {
z-index: 250;
}
.z-max {
z-index: 999999;
}
.overflow-h {
overflow: hidden;
}
// 元素绝对定位的垂直水平居中
.absolute-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// radio 样式重写
input[type="radio"] {
position: relative;
vertical-align: middle;
width: 0.36rem;
height: 0.36rem;
-webkit-appearance: none !important;
-moz-appearance: none;
border: none;
background: none;
outline: none;
}
input[type="radio"]:before {
position: absolute;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
z-index: 100;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:after {
position: absolute;
z-index: 50;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:before {
position: absolute;
z-index: 100;
content: '';
display: block;
width: 0.18rem;
height: 0.18rem;
left: 0.09rem;
top: 0.09rem;
background: #1abc9c;
border-radius: 50%;
border: none;
}
\ No newline at end of file
// flex 参考指南。http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
// 任何一个容器都可以指定 flex 布局
// .box-example { display: flex }
// 行内元素也可以使用 flex 布局
// .box-example { display: inline-flex; }
// 以下6个属性设置在容器上
// 1. flex-direction --> 子项目排列的方向
// row 默认,水平从左到右
// row-reverse 水平从右到左
// column 从上到下
// column-reverse 从下到上
// 2. flex-wrap 默认情况下,子项目都排在一条线上,而此属性解决的是,如果一条线排不下,子项目如何换行
// nowrap 默认,不换行
// wrap 换行,第一行在上方
// wrap-reverse 换行,第一行在下方
// 3. flex-flow 是 flex-direction 和 flex-wrap 的简写形式,默认值为 row nowrap
// 4. justify-content 定义了子项目在主轴上的对齐方式
// flex-start 默认值,左对齐
// flex-end 右对齐
// center 居中
// space-between 两端对齐,子项目之间的间隔相等
// space-around 每个子项目两侧的间隔相等。所以,子项目之间的间隔比子项目与父容器边界的间隔大一倍
// 5. align-items 定义子项目在交叉轴上如何对齐。
// flex-start 交叉轴的起点对齐
// flex-end 交叉轴的终点对齐
// center 交叉轴的中点对齐
// baseline 子项目的第一行文字的基线对齐
// stretch 默认值,如果子项目未设置高度或设为auto,将占满整个容器的高度
// 6. align-content 定义了多根轴线的对齐方式,如果子项目只有一根轴线,则该属性无效。
// flex-start 与交叉轴的起点对齐。
// flex-end 与交叉轴的终点对齐
// center 与交叉轴的中点对齐
// space-between 与交叉轴两端对齐,轴线之间的间隔平均分布。
// space-around 每根轴线两侧的间隔都相等,所以轴线之间的间隔比轴线与边框的间隔大一倍
// stretch 默认值,轴线占满整个交叉轴
// 以下6个属性设置在子项目上。
// 1. order 定义子项目的排列顺序,数值越小,排位越靠前。默认值为0.
// 2. flex-grow 定义子项目放大比例,默认为0,即如果存在剩余空间,也不放大。
// 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。
// 如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
// 3. flex-shrink 定义了子项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
// 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。
// 如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
// 4. flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
// 浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
// 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
// 5. flex 该属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
// 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
// 建议优先使用这个 flex 属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
// align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。
// 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
// 该属性可能取6个值,除了 auto ,其他都与 align-items 属性完全一致。
// ------------------------------------------------------------
\ No newline at end of file
...@@ -423,6 +423,7 @@ module.exports = function(webpackEnv) { ...@@ -423,6 +423,7 @@ module.exports = function(webpackEnv) {
{ {
importLoaders: 2, importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true
}, },
'sass-loader' 'sass-loader'
), ),
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
"less": "^3.9.0", "less": "^3.9.0",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"mini-css-extract-plugin": "0.5.0", "mini-css-extract-plugin": "0.5.0",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "5.0.1", "optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.2.1", "pnp-webpack-plugin": "1.2.1",
"postcss-flexbugs-fixes": "4.1.0", "postcss-flexbugs-fixes": "4.1.0",
......
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom';
import styles from './index.scss'
export default class NavLinks extends Component {
render() {
const { pathUrl, active, icoName, linkName, ...rest } = this.props;
return (
<NavLink
{...rest}
to={pathUrl}
activeClassName={active}
className={styles.root}
>
<i className={icoName + ' ' + styles.ico} />
<span className={styles.text}>{linkName}</span>
</NavLink>
)
}
}
\ No newline at end of file
.root {
flex: auto;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
line-height: 1;
color: #666;
&:hover {
color: #0099ff;
}
}
.ico {
font-size: 0.42rem;
display: block;
margin-bottom: 0.1rem;
}
.text {
display: block;
line-height: 1;
}
\ No newline at end of file
import React, { Component } from 'react';
import NavLink from './NavLink';
import styles from './index.scss';
export default class Nav extends Component {
render() {
return (
<div>
<div style={{ height: '50px' }}></div>
<div className={styles.root}>
<NavLink
pathUrl="/"
exact
icoName={"i-zhuye42un"}
active={styles.navOne}
linkName="首页"
/>
<NavLink
pathUrl="/classify"
icoName="i-haodian42un"
active={styles.navTwo}
linkName="分类"
/>
<NavLink
pathUrl="/study"
icoName="i-youhui42un"
active={styles.navThree}
linkName="学习"
/>
<NavLink
pathUrl="/my"
icoName="i-zhoubian42un"
active={styles.navFour}
linkName="我的"
/>
</div>
</div>
)
}
}
\ No newline at end of file
.root {
height: 50px;
position: fixed;
z-index: 50;
bottom: 0;
left: 0;
width: 100%;
display: flex;
border-top: 1px solid #ccc;
}
.navOne, .navTwo, .navThree, .navFour, .navFive {
color: #09f;
&:hover, &:active {
color: #09f;
}
}
.navOne i:before {
content: "\e93d";
}
.navTwo i:before {
content: "\e917";
}
.navThree i:before {
content: "\e936";
}
.navFour i:before {
content: "\e939";
}
.navFive i:before {
content: "\e913";
}
\ No newline at end of file
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom'
import Tabbar from './components/Tabbar';
import { HOST } from '../../const/host'
class TopTabbar extends Component {
constructor(props) {
super(props)
this.state = {
entry: [
{
name: "曲库",
path: `${HOST}/repertoire`,
icon: require('../../icons/music.png')
},
{
name: "发现",
path: `${HOST}/discover`,
icon: require('../../icons/headphones.png')
},
{
name: "我的",
path: `${HOST}/me`,
icon: require('../../icons/user.png')
},
]
}
}
componentDidMount() {
}
render() {
return (
<div id="top-tabbar">
{
this.state.entry.map(v => (
<NavLink
key={v.path}
to={v.path}
activeClassName="current"
>
<div>
<img src={v.icon} alt="" />
</div>
<div>
{v.name}
</div>
</NavLink>
))
}
</div>
)
}
}
export default TopTabbar
\ No newline at end of file
// 底部路由
export { default as Nav } from './Nav'
\ No newline at end of file
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1555470207785'); /* IE9 */
src: url('iconfont.eot?t=1555470207785#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1555470207785') format('woff'),
url('iconfont.ttf?t=1555470207785') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1555470207785#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icongouwuche:before {
content: "\e669";
}
.iconremen:before {
content: "\e642";
}
.iconerji:before {
content: "\e65f";
}
.iconzhifubaox-:before {
content: "\e650";
}
.iconhuabei:before {
content: "\e78c";
}
.iconweixinzhifu:before {
content: "\e662";
}
.iconyouhuiquan:before {
content: "\e63c";
}
.iconzhong:before {
content: "\e603";
}
.iconiconfront-:before {
content: "\e605";
}
.iconiconfront-1:before {
content: "\e606";
}
.iconiconfront-2:before {
content: "\e607";
}
.iconiconfront-3:before {
content: "\e608";
}
.iconiconfront-4:before {
content: "\e609";
}
.iconiconfront-5:before {
content: "\e60a";
}
.iconiconfront-6:before {
content: "\e60b";
}
.iconiconfront-7:before {
content: "\e60c";
}
.iconiconfront-8:before {
content: "\e60d";
}
.iconiconfront-9:before {
content: "\e60e";
}
.iconiconfront-10:before {
content: "\e60f";
}
.iconiconfront-11:before {
content: "\e610";
}
.iconiconfront-12:before {
content: "\e611";
}
.iconiconfront-13:before {
content: "\e612";
}
.iconiconfront-14:before {
content: "\e613";
}
.iconiconfront-15:before {
content: "\e614";
}
.iconiconfront-16:before {
content: "\e615";
}
.iconiconfront-17:before {
content: "\e616";
}
.iconiconfront-18:before {
content: "\e617";
}
.iconiconfront-19:before {
content: "\e618";
}
.iconiconfront-20:before {
content: "\e619";
}
.iconiconfront-21:before {
content: "\e61a";
}
.iconiconfront-22:before {
content: "\e61b";
}
.iconiconfront-23:before {
content: "\e61c";
}
.iconiconfront-24:before {
content: "\e61d";
}
.iconiconfront-25:before {
content: "\e61e";
}
.iconiconfront-26:before {
content: "\e61f";
}
.iconiconfront-27:before {
content: "\e620";
}
.iconiconfront-28:before {
content: "\e621";
}
.iconiconfront-29:before {
content: "\e622";
}
.iconiconfront-30:before {
content: "\e623";
}
.iconiconfront-31:before {
content: "\e624";
}
.iconiconfront-32:before {
content: "\e625";
}
.iconiconfront-33:before {
content: "\e626";
}
.iconiconfront-34:before {
content: "\e627";
}
.iconiconfront-35:before {
content: "\e628";
}
.iconiconfront-36:before {
content: "\e629";
}
.iconiconfront-37:before {
content: "\e62a";
}
.iconiconfront-38:before {
content: "\e62b";
}
.iconiconfront-39:before {
content: "\e62c";
}
.iconiconfront-40:before {
content: "\e62d";
}
.iconiconfront-41:before {
content: "\e62e";
}
.iconiconfront-42:before {
content: "\e62f";
}
.iconiconfront-43:before {
content: "\e630";
}
.iconiconfront-44:before {
content: "\e631";
}
.iconiconfront-45:before {
content: "\e632";
}
.iconiconfront-46:before {
content: "\e633";
}
.iconiconfront-47:before {
content: "\e634";
}
.iconiconfront-48:before {
content: "\e635";
}
.iconiconfront-49:before {
content: "\e636";
}
.iconiconfront-50:before {
content: "\e637";
}
.iconiconfront-51:before {
content: "\e638";
}
.iconiconfront-52:before {
content: "\e639";
}
.iconiconfront-53:before {
content: "\e63a";
}
.iconiconfront-54:before {
content: "\e63b";
}
.iconiconfront-56:before {
content: "\e63d";
}
.iconiconfront-57:before {
content: "\e63e";
}
.iconiconfront-58:before {
content: "\e63f";
}
.iconiconfront-59:before {
content: "\e640";
}
.iconiconfront-60:before {
content: "\e641";
}
.iconiconfront-63:before {
content: "\e644";
}
.iconiconfront-64:before {
content: "\e645";
}
.iconiconfront-65:before {
content: "\e646";
}
.iconiconfront-66:before {
content: "\e647";
}
.iconiconfront-67:before {
content: "\e648";
}
.iconiconfront-68:before {
content: "\e649";
}
.iconiconfront-69:before {
content: "\e64a";
}
.iconiconfront-70:before {
content: "\e64b";
}
.iconiconfront-71:before {
content: "\e64c";
}
.iconiconfront-72:before {
content: "\e64d";
}
.iconiconfront-73:before {
content: "\e64e";
}
.iconiconfront-74:before {
content: "\e64f";
}
.iconiconfront-76:before {
content: "\e651";
}
.iconiconfront-77:before {
content: "\e652";
}
.icondanseshixintubiao-:before {
content: "\e653";
}
.icondanseshixintubiao-1:before {
content: "\e654";
}
.icondanseshixintubiao-2:before {
content: "\e655";
}
.icondanseshixintubiao-3:before {
content: "\e656";
}
.icondanseshixintubiao-4:before {
content: "\e657";
}
.icondanseshixintubiao-5:before {
content: "\e658";
}
.icondanseshixintubiao-6:before {
content: "\e659";
}
.icondanseshixintubiao-7:before {
content: "\e65a";
}
.icondanseshixintubiao-8:before {
content: "\e65b";
}
.icondanseshixintubiao-9:before {
content: "\e65c";
}
.icondanseshixintubiao-10:before {
content: "\e65d";
}
.icondanseshixintubiao-11:before {
content: "\e65e";
}
.icondanseshixintubiao-13:before {
content: "\e660";
}
.icondanseshixintubiao-14:before {
content: "\e661";
}
.icondanseshixintubiao-16:before {
content: "\e663";
}
.icondanseshixintubiao-17:before {
content: "\e664";
}
.icondanseshixintubiao-12:before {
content: "\e643";
}
.icondanseshixintubiao-23:before {
content: "\e66a";
}
.icondanseshixintubiao-24:before {
content: "\e66b";
}
.icondanseshixintubiao-25:before {
content: "\e66c";
}
.icondanseshixintubiao-29:before {
content: "\e670";
}
.icondanseshixintubiao-30:before {
content: "\e671";
}
.icondanseshixintubiao-32:before {
content: "\e673";
}
.icondanseshixintubiao-35:before {
content: "\e676";
}
.iconfridge:before {
content: "\e674";
}
.icontea:before {
content: "\e67a";
}
.iconfish:before {
content: "\e67b";
}
.iconfrench_fries:before {
content: "\e675";
}
.iconramen:before {
content: "\e67c";
}
.iconhoney:before {
content: "\e67d";
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'; ...@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom';
import Router from './router'; import Router from './router';
// import { Provider } from 'react-redux'; // import { Provider } from 'react-redux';
import './index.css'; import './styles/index.scss';
// import App from './App'; // import App from './App';
ReactDOM.render( ReactDOM.render(
......
import React from 'react' import React from 'react'
import { Nav} from './common'
import { TabBar } from 'antd-mobile'
import { Link } from 'react-router-dom';
class menu extends React.Component { class menu extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.onPress = this.onPress.bind(this);
}
onPress(item) {
this.setState({ selected: item })
}
render(match) { render(match) {
let { selected = 'index' } = this.state;
return ( return (
<div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}> <div className='tabbar' style={{ position: "fixed", width: "100%", bottom: 0 }}>
<TabBar> <Nav />
<TabBar.Item
title="首页"
key="home"
icon={<Link to='/index'><i className='iconfont icon-youhuijuan tabbarIcon' >121212</i> </Link>}
selectedIcon={<Link to='/index'><i className='iconfont icon-youhuijuan selectedTabbarIcon' ></i> </Link>}
selected={selected === 'index' ? true : false}
onPress={() => { this.onPress('index') }}
/>
<TabBar.Item
title="分类"
key="classify"
icon={<Link to='/classify'><i className='iconfont icon-zhangdan-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/classify'><i className='iconfont icon-zhangdan-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'classify' ? true : false}
onPress={() => { this.onPress('classify') }}
/>
<TabBar.Item
title="学习"
key="study"
icon={<Link to='/study'><i className='iconfont icon-zhangdan-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/study'><i className='iconfont icon-zhangdan-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'study' ? true : false}
onPress={() => { this.onPress('study') }}
/>
<TabBar.Item
title="我的"
key="my"
icon={<Link to='/my'><i className='iconfont icon-yonghu-xianxing tabbarIcon' >121212</i></Link>}
selectedIcon={<Link to='/my'><i className='iconfont icon-yonghu-xianxing selectedTabbarIcon' ></i> </Link>}
selected={selected === 'my' ? true : false}
onPress={() => { this.onPress('my') }}
/>
</TabBar>
</div> </div>
) )
} }
......
import React from 'react' import React from 'react'
import { HashRouter as Router, Route } from "react-router-dom"; import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import Menu from './menu';
import Index from './components/Index';
import Classify from './components/classify';
import Study from './components/study';
import My from './components/my';
import Main from './main'
const router = () => ( const router = () => (
<Router> <Router>
<Route path='/' component={Main}> {/* <div style={{ backgroundColor: 'rgb(245, 245, 249)', textAlign: 'center' }}> */}
</Route>
<Switch>
<Route exact path="/" component={Index}></Route>
<Route path="/index" component={Index}></Route>
<Route path='/classify' component={Classify}></Route>
<Route path='/study' component={Study}></Route>
<Route path='/my' component={My}></Route>
</Switch>
<Menu />
{/* </div> */}
</Router> </Router>
) )
......
// 使用建议
// --------------------------------------------------
// CSS Modules 是对现有的 CSS 做减法。为了追求简单可控,建议遵循如下原则:
// ·不使用选择器(id,伪类,标签等),只使用class名来定义样式
// ·不层叠多个class,只使用一个class把所有样式定义好
// ·所有样式通过 composes 组合来实现复用
// ·不嵌套
// --------------------------------------------------
// 公有样式引入mixins的目的是为了方便默认设置若干常用的样式
// 公有样式不可以使用composes
// @import "./mixins.scss";
// 颜色设置
$border-color: #e9e9e9; //边框颜色
$body-color: #333; //设置通用的字体颜色
$body-bg: #f2f2f2; //设置通用的 body 背景色
$link-color: #333; //设置通用的链接颜色
$link-visited: #333; //设置链接访问后的颜色
$main-color: #1BBC9B; //主体颜色
// 字体
$font-family-zh: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
$font-family-en: Arial, sans-serif !default;
// 盒子模型
$box-model: border-box !default;
// z-index
$z-50: 50;
$z-100: 100;
$z-150: 150;
$z-200: 200;
$z-250: 250;
$z-max: 999999; //为了应付某些插件z-index 值过高的问题
// 全局设置
// --------------------------------------------------
//
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
border: 0 none;
font-size: inherit;
color: inherit;
margin: 0;
padding: 0;
vertical-align: baseline;
/* 在X5新内核Blink中,在排版页面的时候,会主动对字体进行放大,会检测页面中的主字体,当某一块字体在我们的判定规则中,认为字号较小,并且是页面中的主要字体,就会采取主动放大的操作。然而这不是我们想要的,可以采取给最大高度解决 */
max-height: 100000px;
}
h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
em, strong {
font-style: normal;
}
ul, ol, li {
list-style: none;
}
// 全局盒子模型设置
* {
box-sizing: $box-model;
}
*:before,
*:after {
box-sizing: $box-model;
}
// -webkit-tap-highlight-color 是一个 不规范的属性,它没有出现在 CSS 规范草案中。
// 当用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色。
html {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
font-family: $font-family-zh;
line-height: 1.5;
color: $body-color;
background-color: $body-bg;
font-size: 0.24rem;
}
// Links
a {
text-decoration: none;
outline: none;
&:hover,
&:link,
&:focus {
text-decoration: none;
}
&:visited {
}
}
// 暂时放置样式,后期需处理
.homeImg {
display: block;
width: 100%;
}
// 字体颜色
.main-color {
color: $main-color;
}
.color333 {
color: #333
}
.color666 {
color: #666
}
.color999 {
color: #999
}
// 背景颜色
.bg-white { background-color: #fff }
// 间隔
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt50 {
padding-top: 50px;
}
.pt60 {
padding-top: 60px;
}
.plr20 {
padding-left: 0.2rem;
padding-right: 0.2rem;
}
// 请保证你的设计稿为750px宽,如果有其余字体大小,请在私有样式中设置
.font-20 {font-size: 0.2rem;}
.font-24 {font-size: 0.24rem;}
.font-26 {font-size: 0.26rem;}
.font-28 {font-size: 0.28rem;}
.font-30 {font-size: 0.3rem;}
.font-32 {font-size: 0.32rem;}
.font-34 {font-size: 0.34rem;}
.font-36 {font-size: 0.36rem;}
.font-38 {font-size: 0.38rem;}
.font-40 {font-size: 0.4rem;}
// 设置block
.block {
display: block;
}
.show {
display: inherit;
}
.hide {
display: none;
}
// 最外层页面设置
.box {
max-width: 10rem;
margin-left: auto;
margin-right: auto;
}
// 半透明弹层
.alert-bg {
position: fixed;
z-index: $z-50;
width: 100%;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
display: none; //注意:默认隐藏!!
}
.alpha-bg {
position: fixed;
z-index: 100;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
}
// 布局相关
// 水平
.hor {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
// 水平居中
.hor-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
// 垂直居中
.ver-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
// 子元素内联垂直居中
.center-center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 子元素块联水平垂直居中
.center-center-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
// 两边对齐
.space-between {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
// last-no-border
.last-no-border:last-child {
border: none;
background: none;
}
// 图片设置
img {
max-width: 100%;
}
.img-responsive {
display: block;
width: 100%;
}
// 这里主要应付 antd-mobile 的组件carousel 不能等比缩放的蛋疼问题
.home-swipe {
height: 40.625vw;
max-height: 406.25px;
}
// 文本控制类
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
// 字符溢出隐藏
.text-overflow-1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 字符超出一行溢出隐藏
.text-overflow-one {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
// 字符超出两行溢出隐藏
.text-overflow-2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 字符超出三行溢出隐藏
.text-overflow-3 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
// 浮动控制
.cf {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.fl {
float: left;
}
.fr {
float: right;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.z-150 {
z-index: 150;
}
.z-200 {
z-index: 200;
}
.z-250 {
z-index: 250;
}
.z-max {
z-index: 999999;
}
.overflow-h {
overflow: hidden;
}
// 元素绝对定位的垂直水平居中
.absolute-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// radio 样式重写
input[type="radio"] {
position: relative;
vertical-align: middle;
width: 0.36rem;
height: 0.36rem;
-webkit-appearance: none !important;
-moz-appearance: none;
border: none;
background: none;
outline: none;
}
input[type="radio"]:before {
position: absolute;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
z-index: 100;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:after {
position: absolute;
z-index: 50;
content: '';
display: block;
width: 0.36rem;
height: 0.36rem;
border: 2px solid #999;
background: #fff;
left: 0;
top: 0;
border-radius: 50%;
outline: 0;
}
input[type="radio"]:checked:before {
position: absolute;
z-index: 100;
content: '';
display: block;
width: 0.18rem;
height: 0.18rem;
left: 0.09rem;
top: 0.09rem;
background: #1abc9c;
border-radius: 50%;
border: none;
}
\ No newline at end of file
// flex 参考指南。http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
// 任何一个容器都可以指定 flex 布局
// .box-example { display: flex }
// 行内元素也可以使用 flex 布局
// .box-example { display: inline-flex; }
// 以下6个属性设置在容器上
// 1. flex-direction --> 子项目排列的方向
// row 默认,水平从左到右
// row-reverse 水平从右到左
// column 从上到下
// column-reverse 从下到上
// 2. flex-wrap 默认情况下,子项目都排在一条线上,而此属性解决的是,如果一条线排不下,子项目如何换行
// nowrap 默认,不换行
// wrap 换行,第一行在上方
// wrap-reverse 换行,第一行在下方
// 3. flex-flow 是 flex-direction 和 flex-wrap 的简写形式,默认值为 row nowrap
// 4. justify-content 定义了子项目在主轴上的对齐方式
// flex-start 默认值,左对齐
// flex-end 右对齐
// center 居中
// space-between 两端对齐,子项目之间的间隔相等
// space-around 每个子项目两侧的间隔相等。所以,子项目之间的间隔比子项目与父容器边界的间隔大一倍
// 5. align-items 定义子项目在交叉轴上如何对齐。
// flex-start 交叉轴的起点对齐
// flex-end 交叉轴的终点对齐
// center 交叉轴的中点对齐
// baseline 子项目的第一行文字的基线对齐
// stretch 默认值,如果子项目未设置高度或设为auto,将占满整个容器的高度
// 6. align-content 定义了多根轴线的对齐方式,如果子项目只有一根轴线,则该属性无效。
// flex-start 与交叉轴的起点对齐。
// flex-end 与交叉轴的终点对齐
// center 与交叉轴的中点对齐
// space-between 与交叉轴两端对齐,轴线之间的间隔平均分布。
// space-around 每根轴线两侧的间隔都相等,所以轴线之间的间隔比轴线与边框的间隔大一倍
// stretch 默认值,轴线占满整个交叉轴
// 以下6个属性设置在子项目上。
// 1. order 定义子项目的排列顺序,数值越小,排位越靠前。默认值为0.
// 2. flex-grow 定义子项目放大比例,默认为0,即如果存在剩余空间,也不放大。
// 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。
// 如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍
// 3. flex-shrink 定义了子项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
// 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。
// 如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
// 4. flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
// 浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
// 它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
// 5. flex 该属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
// 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
// 建议优先使用这个 flex 属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
// align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。
// 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
// 该属性可能取6个值,除了 auto ,其他都与 align-items 属性完全一致。
// ------------------------------------------------------------
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment