weex-ui-demo
Version:
A rich interaction, lightweight, high performance UI library based on Weex
303 lines (279 loc) • 9.02 kB
JavaScript
const path = require('path');
const fs = require('fs-extra');
const uppercamelize = require('uppercamelcase');
const webpack = require('webpack');
const config = require('./config');
const helper = require('./helper');
const glob = require('glob');
const vueLoaderConfig = require('./vue-loader.conf');
const vueWebTemp = helper.rootNode(config.templateDir);
const hasPluginInstalled = fs.existsSync(helper.rootNode(config.pluginFilePath));
const isWin = /^win/.test(process.platform);
const webEntry = {};
const weexEntry = {};
// Wraping the entry file for web.
const getWebEntryFileContent = (entryPath, vueFilePath) => {
let relativeVuePath = path.relative(path.join(entryPath, '../'), vueFilePath);
let relativeEntryPath = helper.root(config.entryFilePath);
let relativePluginPath = helper.rootNode(config.pluginFilePath);
let contents = '';
let entryContents = fs.readFileSync(relativeEntryPath).toString();
if (isWin) {
relativeVuePath = relativeVuePath.replace(/\\/g, '\\\\');
relativePluginPath = relativePluginPath.replace(/\\/g, '\\\\');
}
if (hasPluginInstalled) {
contents += `\n// If detact plugins/plugin.js is exist, import and the plugin.js\n`;
contents += `import plugins from '${relativePluginPath}';\n`;
contents += `plugins.forEach(function (plugin) {\n\tweex.install(plugin)\n});\n\n`;
entryContents = entryContents.replace(/weex\.init/, match => `${contents}${match}`);
contents = ''
}
// NOTE: web端不打包下面的代码
// contents += `
// const App = require('${relativeVuePath}');
// new Vue(Vue.util.extend({el: '#root'}, App));
// `;
return entryContents + contents;
}
// Wraping the entry file for native.
const getNativeEntryFileContent = (entryPath, vueFilePath) => {
let relativeVuePath = path.relative(path.join(entryPath, '../'), vueFilePath);
let contents = '';
if (isWin) {
relativeVuePath = relativeVuePath.replace(/\\/g, '\\\\');
}
contents += `import App from '${relativeVuePath}'
App.el = '#root'
new Vue(App)
`;
return contents;
}
// Retrieve entry file mappings by function recursion
const getEntryFile = (dir) => {
dir = dir || config.sourceDir;
const entries = glob.sync(`${dir}/${config.entryFilter}`, config.entryFilterOptions);
entries.forEach(entry => {
const extname = path.extname(entry);
const basename = entry.replace(`${dir}/`, '').replace(extname, '');
const templatePathForWeb = path.join(vueWebTemp, basename + '.web.js');
const templatePathForNative = path.join(vueWebTemp, basename + '.js');
fs.outputFileSync(templatePathForWeb, getWebEntryFileContent(templatePathForWeb, entry));
fs.outputFileSync(templatePathForNative, getNativeEntryFileContent(templatePathForNative, entry));
webEntry[basename] = templatePathForWeb;
weexEntry[basename] = templatePathForNative;
})
}
// Generate an entry file array before writing a webpack configuration
getEntryFile();
// getRoutes
const getRoutes = () => {
let routesConfig = fs.readFileSync(helper.root('/routes/config.json')).toString();
routesConfig = JSON.parse(routesConfig)
let routes = []
let entry = {}
for (let key in routesConfig) {
if (entry[routesConfig[key].type]) {
entry[routesConfig[key].type].push(`'${key}'`)
} else {
entry[routesConfig[key].type] = []
}
routes.push(`{ path: '${routesConfig[key].path}', component: require('@/${routesConfig[key].jsPath}') }`)
}
const content =
`// index.js由webpack打包生成,无需更改
export default ${JSON.stringify(routes, null, 2).replace(/"/g, '')}\n`
const examples =
`// examples.js由webpack打包生成,无需更改
export default ${JSON.stringify(entry, null, 2).replace(/"/g, '')}\n`
fs.outputFileSync(helper.root('/routes/example.conf.js'), examples)
fs.outputFileSync(helper.root('/routes/index.js'), content)
}
getRoutes()
// getIndexEntry
const getIndexEntry = () => {
const components = fs.readdirSync(helper.rootNode('packages')).filter(name => name !== 'style')
const importList = components.map(name => `import ${uppercamelize(name)} from './packages/${name}'`)
const exportList = components.map(name => `${uppercamelize(name)}`)
const content =
`// examples.js由webpack打包生成,无需更改
${importList.join('\n')}
export {
${exportList.join(',\n ')}
}\n`
fs.writeFileSync(path.join(__dirname, '../index.js'), content)
}
getIndexEntry()
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [helper.rootNode('src'), helper.rootNode('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
const useEslint = config.dev.useEslint ? [createLintingRule()] : []
/**
* Plugins for webpack configuration.
*/
const plugins = [
/**
* Plugin: webpack.DefinePlugin
* Description: The DefinePlugin allows you to create global constants which can be configured at compile time.
*
* See: https://webpack.js.org/plugins/define-plugin/
*/
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': config.dev.env
}
}),
/*
* Plugin: BannerPlugin
* Description: Adds a banner to the top of each generated chunk.
* See: https://webpack.js.org/plugins/banner-plugin/
*/
new webpack.BannerPlugin({
banner: '// { "framework": "Vue"} \n',
raw: true,
exclude: 'Vue'
})
];
// Config for compile jsbundle for web.
const webConfig = {
entry: Object.assign(webEntry, {
'vendor': [path.resolve('node_modules/phantom-limb/index.js')]
}),
output: {
path: helper.rootNode('../dist'),
filename: '[name].web.js'
},
/**
* Options affecting the resolving of modules.
* See http://webpack.github.io/docs/configuration.html#resolve
*/
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': helper.resolve('src'),
packages: path.resolve(__dirname, '../packages')
}
},
/*
* Options affecting the resolving of modules.
*
* See: http://webpack.github.io/docs/configuration.html#module
*/
module: {
// webpack 2.0
rules: useEslint.concat([
{
test: /\.js$/,
use: [{
loader: 'babel-loader'
}],
exclude: config.excludeModuleReg
},
{
test: /\.vue(\?[^?]+)?$/,
use: [{
loader: 'vue-loader',
options: Object.assign(vueLoaderConfig({useVue: true, usePostCSS: false}), {
/**
* important! should use postTransformNode to add $processStyle for
* inline style prefixing.
*/
optimizeSSR: false,
postcss: [
// to convert weex exclusive styles.
require('postcss-plugin-weex')(),
require('autoprefixer')({
browsers: ['> 0.1%', 'ios >= 8', 'not ie < 12']
}),
require('postcss-plugin-px2rem')({
// base on 750px standard.
rootValue: 75,
// to leave 1px alone.
minPixelValue: 1.01
})
],
compilerModules: [
{
postTransformNode: el => {
// to convert vnode for weex components.
require('weex-vue-precompiler')()(el)
}
}
]
})
}],
exclude: config.excludeModuleReg
}
])
},
/*
* Add additional plugins to the compiler.
*
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: plugins
};
// Config for compile jsbundle for native.
const weexConfig = {
entry: weexEntry,
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].js'
},
/**
* Options affecting the resolving of modules.
* See http://webpack.github.io/docs/configuration.html#resolve
*/
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': helper.resolve('src'),
packages: path.resolve(__dirname, '../packages')
}
},
/*
* Options affecting the resolving of modules.
*
* See: http://webpack.github.io/docs/configuration.html#module
*/
module: {
rules: [
{
test: /\.js$/,
use: [{
loader: 'babel-loader'
}],
exclude: config.excludeModuleReg
},
{
test: /\.vue(\?[^?]+)?$/,
use: [{
loader: 'weex-loader',
options: vueLoaderConfig({useVue: false})
}],
exclude: config.excludeModuleReg
}
]
},
/*
* Add additional plugins to the compiler.
*
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: plugins,
/*
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.github.io/docs/configuration.html#node
*/
node: config.nodeConfiguration
};
module.exports = [webConfig, weexConfig];