Repository: wechat-miniprogram/kbone-template-react Branch: master Commit: 5f9ae76b4002 Files: 15 Total size: 16.2 KB Directory structure: gitextract_ok9soqir/ ├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── build/ │ ├── miniprogram.config.js │ ├── webpack.base.config.js │ ├── webpack.dev.config.js │ ├── webpack.mp.config.js │ └── webpack.prod.config.js ├── index.html ├── package.json └── src/ ├── components/ │ └── counter/ │ ├── index.css │ └── index.jsx ├── index.jsx └── log.jsx ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": [ "env", "stage-3", "react" ], "plugins": [ "transform-runtime" ] } ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env # next.js build output .next # others .idea .DS_Store dist ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 wechat-miniprogram Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # react-kbone 使用 react 多端开发(小程序和Web),基于 [kbone](https://github.com/Tencent/kbone) 的 element 和 render。 ## 特性 * 一键接入,立即使用 * 支持完整 JSX 语法,任意位置任意方式书写 JSX ## 一套语法多端运行 ```jsx function Counter() { const [count, setCount] = useState(0) return (
{count}
跳转
) } function clickHandle() { if ('undefined' != typeof wx && wx.getSystemInfoSync) { wx.navigateTo({ url: '../log/index?id=1', }) } else { location.href = 'log.html' } } export default Counter ``` ## 快速开始 ``` npx kbone-cli init my-app cd my-app npm run mp // 开发小程序 npm run build:mp // 构建小程序 npm run web // 开发 web npm run build // 构建 web ``` ## 目录说明 ``` ├─ dist │ ├─ mp // 微信开发者工具指向的目录,用于生产环境 │ ├─ web // web 编译出的文件,用于生产环境 ├─ build // 构建相关 ├─ src │ ├─ assets │ ├─ components // 存放所有组件 │ ├─ log.jsx // 入口文件,会 build 成 log.html │ └─ index.jsx // 入口文件,会 build 成 index.html ``` ## 注意事项 react 并没有提供根组件实例的销毁方法(如 vue.$destroy),所以在多页应用中页面关闭时不会触发该页面组件的 componentWillUnmount 钩子。开发者可自行监听 wxunload 或 beforeunload 事件来进行页面的销毁工作,比如调用 render 方法渲染一个空节点,强行触发页面组件的 componentWillUnmount 钩子。 ## 谁在使用 kbone?
告诉我们
## License MIT ================================================ FILE: build/miniprogram.config.js ================================================ /** * 配置参考:https://wechat-miniprogram.github.io/kbone/docs/config/ */ module.exports = { origin: 'https://test.miniprogram.com', entry: '/', router: { home: [ '/(home|index)?', '/index.html', '/test/(home|index)', ], other: [ '/test/list/:id', '/test/detail/:id', ], }, redirect: { notFound: 'home', accessDenied: 'home', }, generate: { autoBuildNpm: 'npm', }, app: { navigationBarTitleText: 'miniprogram-project', }, appExtraConfig: { sitemapLocation: 'sitemap.json', }, global: {}, pages: {}, optimization: { domSubTreeLevel: 10, elementMultiplexing: true, textMultiplexing: true, commentMultiplexing: true, domExtendMultiplexing: true, styleValueReduce: 5000, attrValueReduce: 5000, }, projectConfig: { projectname: 'kbone-template-react', appid: '', }, } ================================================ FILE: build/webpack.base.config.js ================================================ const path = require('path') module.exports = { context: path.resolve(__dirname, '../'), entry: { index: path.resolve(__dirname, '../src/index.jsx'), log: path.resolve(__dirname, '../src/log.jsx'), }, output: { path: path.resolve(__dirname, '../dist/web'), filename: '[name].js', publicPath: '/', }, module: { rules: [ { test: /\.[t|j]sx?$/, loader: 'babel-loader', exclude: /node_modules/, }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]', }, }, ], }, resolve: { extensions: ['*', '.js', '.jsx', '.json'] }, } ================================================ FILE: build/webpack.dev.config.js ================================================ const webpack = require('webpack') const { merge } = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.config') const HtmlWebpackPlugin = require('html-webpack-plugin') const portfinder = require('portfinder') const htmlPluginList = Object.keys(baseWebpackConfig.entry).map(name => { return new HtmlWebpackPlugin({ filename: `${name}.html`, template: 'index.html', inject: true, chunks: [name], }) }) const devWebpackConfig = merge(baseWebpackConfig, { mode: 'development', devServer: { historyApiFallback: { rewrites: [{from: /.*/, to: '/index.html'}], }, hot: true, compress: true, host: process.env.HOST || 'localhost', port: +process.env.PORT || 8080, open: true, // 自动打开浏览器 client: { logging: 'warn', overlay: { // 展示全屏报错 warnings: false, errors: true }, }, static: { publicPath: '/', }, proxy: {}, }, watchOptions: { poll: false, }, devtool: 'cheap-module-eval-source-map', module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'], }, ], }, plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"development"', }, }), new webpack.HotModuleReplacementPlugin(), ...htmlPluginList, ], }) module.exports = new Promise((resolve, reject) => { portfinder.basePort = +process.env.PORT || 8080 portfinder.getPort((err, port) => { if (err) { reject(err) } else { devWebpackConfig.devServer.port = port resolve(devWebpackConfig) } }) }) ================================================ FILE: build/webpack.mp.config.js ================================================ const path = require('path') const webpack = require('webpack') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') const TerserPlugin = require('terser-webpack-plugin') const MpPlugin = require('mp-webpack-plugin') const isOptimize = false // 是否压缩业务代码,开发者工具可能无法完美支持业务代码使用到的 es 特性,建议自己做代码压缩 module.exports = { mode: 'production', entry: { index: path.resolve(__dirname, '../src/index.jsx'), log: path.resolve(__dirname, '../src/log.jsx'), }, output: { path: path.resolve(__dirname, '../dist/mp/common'), // 放到小程序代码目录中的 common 目录下 filename: '[name].js', // 必需字段,不能修改 library: 'createApp', // 必需字段,不能修改 libraryExport: 'default', // 必需字段,不能修改 libraryTarget: 'window', // 必需字段,不能修改 }, target: 'web', // 必需字段,不能修改 optimization: { runtimeChunk: false, // 必需字段,不能修改 splitChunks: { // 代码分隔配置,不建议修改 chunks: 'all', minSize: 1000, maxSize: 0, minChunks: 1, maxAsyncRequests: 100, maxInitialRequests: 100, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, minimizer: isOptimize ? [ // 压缩CSS new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.(css|wxss)$/g, cssProcessor: require('cssnano'), cssProcessorPluginOptions: { preset: [ 'default', { discardComments: { removeAll: true, }, minifySelectors: false, // 因为 wxss 编译器不支持 .some>:first-child 这样格式的代码,所以暂时禁掉这个 }, ], }, canPrint: false, }), // 压缩 js new TerserPlugin({ test: /\.js(\?.*)?$/i, parallel: true, }), ] : [], }, module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'], }, { test: /\.[t|j]sx?$/, loader: 'babel-loader', exclude: /node_modules/, }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]', }, }, ], }, resolve: { extensions: ['*', '.js', '.jsx', '.json'], }, plugins: [ new webpack.DefinePlugin({ 'process.env.isMiniprogram': process.env.isMiniprogram, // 注入环境变量,用于业务代码判断 }), new MiniCssExtractPlugin({ filename: '[name].wxss', }), new MpPlugin(require('./miniprogram.config')), ], } ================================================ FILE: build/webpack.prod.config.js ================================================ const path = require('path') const webpack = require('webpack') const { merge } = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.config') const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') const TerserPlugin = require('terser-webpack-plugin') const htmlPluginList = Object.keys(baseWebpackConfig.entry).map(name => { return new HtmlWebpackPlugin({ filename: path.resolve(__dirname, `../dist/web/${name}.html`), template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true, }, chunks: [name], }) }) const webpackConfig = merge(baseWebpackConfig, { mode: 'production', output: { path: path.resolve(__dirname, '../dist/web'), filename: path.posix.join('static', 'js/[name].[chunkhash].js'), chunkFilename: path.posix.join('static', 'js/[id].[chunkhash].js'), }, optimization: { splitChunks: { // 代码分割配置 chunks: 'async', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, minimizer: [ // 压缩CSS new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), cssProcessorPluginOptions: { preset: [ 'default', { discardComments: { removeAll: true, }, }, ], }, canPrint: false, }), // 压缩 js new TerserPlugin({ test: /\.js(\?.*)?$/i, parallel: true, }), ], }, devtool: false, module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'], }, ], }, plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"', }, }), // 分离 css 文件 new MiniCssExtractPlugin({ filename: path.posix.join('static', 'css/[name].[hash].css'), }), ...htmlPluginList, // 当 vendor 模块没有改变时,保证模块 id 不变 new webpack.HashedModuleIdsPlugin(), ], }) module.exports = webpackConfig ================================================ FILE: index.html ================================================ react
================================================ FILE: package.json ================================================ { "name": "react-kbone", "version": "0.0.1", "description": "", "author": "wechat-miniprogram", "keywords": [ "react", "kbone", "mp" ], "scripts": { "start": "npm run mp", "web": "cross-env NODE_ENV=development webpack-dev-server --progress --config build/webpack.dev.config.js", "mp": "rimraf dist/mp/common && cross-env NODE_ENV=development webpack --config build/webpack.mp.config.js --watch --progress", "build": "rimraf dist/web && cross-env NODE_ENV=production webpack --config build/webpack.prod.config.js --progress", "build:mp": "rimraf dist/mp/common && cross-env NODE_ENV=production webpack --config build/webpack.mp.config.js --progress" }, "dependencies": { "react": "^16.9.0", "react-dom": "^16.9.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ], "devDependencies": { "@webpack-cli/serve": "^1.6.1", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-3": "^6.24.1", "cross-env": "^5.0.5", "css-loader": "^0.28.7", "file-loader": "^1.1.4", "html-webpack-plugin": "^4.5.2", "mini-css-extract-plugin": "^0.5.0", "mp-webpack-plugin": "latest", "optimize-css-assets-webpack-plugin": "^5.0.8", "portfinder": "^1.0.28", "rimraf": "^2.7.1", "style-loader": "^2.0.0", "stylehacks": "^4.0.3", "terser-webpack-plugin": "^4.2.3", "webpack": "^4.29.6", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4", "webpack-merge": "^5.8.0" }, "license": "MIT" } ================================================ FILE: src/components/counter/index.css ================================================ span{ color: red; } ================================================ FILE: src/components/counter/index.jsx ================================================ import React, { useState } from 'react' import './index.css' function Counter() { const [count, setCount] = useState(0) return (
{count}
跳转
) } function clickHandle() { if ('undefined' != typeof wx && wx.getSystemInfoSync) { wx.navigateTo({ url: '../log/index?id=1', }) } else { location.href = 'log.html' } } export default Counter ================================================ FILE: src/index.jsx ================================================ import React from 'react' import ReactDOM from 'react-dom' import Counter from './components/counter' export default function createApp() { const container = document.createElement('div') container.id = 'app' document.body.appendChild(container) ReactDOM.render(, container) } ;('undefined' != typeof wx && wx.getSystemInfoSync) || createApp() ================================================ FILE: src/log.jsx ================================================ import React from 'react' import ReactDOM from 'react-dom' export default function createApp() { const container = document.createElement('div') container.id = 'app' document.body.appendChild(container) ReactDOM.render(
我是log页面
, container) } ;('undefined' != typeof wx && wx.getSystemInfoSync) || createApp()