process.env.ENTRY_INDEX = 'dev'; const fs = require('fs'); const path = require('path'); const chokidar = require('chokidar'); const importFresh = require('import-fresh'); const replace = require('json-templater/string'); const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); const devWebpack = require('./webpack.dev.conf'); const configPath = path.join(__dirname, './config.js'); let { devComponent } = require('./config'); const componentsInPrototype = ['Modal', 'message', 'notification']; const MAIN_TEMPLATE = `import 'babel-polyfill'; import './index.less'; import 'highlight.js/styles/solarized-light.css'; import Vue from 'vue'; import Vuex from 'vuex'; import VueI18n from 'vue-i18n'; import VueRouter from 'vue-router'; import VueClipboard from 'vue-clipboard2'; import Md from './components/md'; import Api from './components/api'; import demoBox from './components/demoBox'; import demoContainer from './components/demoContainer'; import Modal from '../components/modal'; import message from '../components/message'; import notification from '../components/notification'; {{importComponents}} {{importStyles}} import '../components/modal/style'; import '../components/message/style'; import '../components/notification/style'; import Test from '../components/{{name}}/demo/index.vue'; import zhCN from './theme/zh-CN'; import enUS from './theme/en-US'; Vue.use(Vuex); Vue.use(VueClipboard); Vue.use(VueRouter); Vue.use(VueI18n); Vue.component(Md.name, Md); Vue.component(Api.name, Api); Vue.component('demo-box', demoBox); Vue.component('demo-container', demoContainer); Vue.prototype.$message = message; Vue.prototype.$notification = notification; Vue.prototype.$info = Modal.info; Vue.prototype.$success = Modal.success; Vue.prototype.$error = Modal.error; Vue.prototype.$warning = Modal.warning; Vue.prototype.$confirm = Modal.confirm; Vue.prototype.$destroyAll = Modal.destroyAll; Vue.use(Modal); {{install}} const i18n = new VueI18n({ locale: enUS.locale, messages: { [enUS.locale]: { message: enUS.messages }, [zhCN.locale]: { message: zhCN.messages }, }, }); const router = new VueRouter({ mode: 'history', routes: [{ path: '/*', component: Test }], }); const store = new Vuex.Store({ state: { username: 'zeka', }, mutations: { update(state, payload) { state.username = payload.username; }, }, }); new Vue({ el: '#app', i18n, router, store, }); `; const OUTPUT_PATH = path.join(__dirname, '../site/dev.js'); const generateEntry = components => Object.keys(components) .map(component => `import ${component} from '../components/${components[component]}';`) .join('\n'); const generateStyles = components => Object.keys(components) .map(component => `import '../components/${components[component]}/style';`) .join('\n'); const generateInstall = components => Object.keys(components) .map(component => `Vue.use(${component});`) .join('\n'); const renderTemplate = name => { const components = { Tooltip: 'tooltip', // for DemoBox }; const demoPaths = fs.readdirSync(path.join(__dirname, `../components/${name}/demo`)); demoPaths.forEach(demoPath => { const demo = fs .readFileSync(path.join(__dirname, `../components/${name}/demo/${demoPath}`)) .toString(); const componentsInDemo = demo.match(/a-(\w+(-\w+)*)/g) || []; componentsInDemo.forEach(name => { const componentName = name.replace(/-(\w)/g, ($, $1) => $1.toUpperCase()).replace(/^a/, ''); if (componentsInPrototype.includes(componentName)) { return; } const componentPath = path.join(__dirname, `../components/${name.replace(/^a-/, '')}`); if (fs.existsSync(componentPath)) { components[componentName] = name.replace(/^a-/, ''); } }); }); const importComponents = generateEntry(components); const importStyles = generateStyles(components); const install = generateInstall(components); const template = replace(MAIN_TEMPLATE, { importComponents, importStyles, install, name, }); fs.writeFileSync(OUTPUT_PATH, template); }; let demoWatcher; chokidar.watch(configPath, { ignoreInitial: true }).on('change', async () => { devComponent = importFresh(configPath).devComponent; demoWatcher && (await demoWatcher.close()); demoWatcher = chokidar.watch(path.join(__dirname, `../components/${devComponent}/demo`)); demoWatcher.on('change', () => { renderTemplate(devComponent); }); renderTemplate(devComponent); }); renderTemplate(devComponent); const compiler = webpack(devWebpack); const configuration = devWebpack.devServer; const server = new WebpackDevServer(compiler, configuration); server.listen(configuration.port);