Commit c3d864f3 authored by 尚斌杰's avatar 尚斌杰

update

parent 550dc2f6
# vue-cli3多页开发插件
### 新建页面
npm run add [page]
### 构建页面
npm run build [page1+page2] or npm run build [page1]
\ No newline at end of file
const {
info
} = require('@vue/cli-shared-utils')
const path = require('path')
const resolve = require('resolve')
const chalk = require('chalk')
const copy = require('copy')
const baseDir = resolve.sync('vue-cli-plugin-multi-pages', { basedir: process.cwd() })
const source = path.resolve(path.dirname(baseDir), 'generator/template/**')
const dist = 'src/pages/'
module.exports = (api, options) => {
} = require('@vue/cli-shared-utils')
const ejs = require('ejs')
const fs = require('fs')
const copy = require('copy')
const resolve = require('resolve')
const path = require('path')
const chalk = require('chalk')
const inquirer = require('inquirer')
const baseDir = resolve.sync('vue-cli-plugin-multi-pages', { basedir: process.cwd() })
const source = path.resolve(path.dirname(baseDir), 'generator/template/**')
module.exports = (api, opts)=>{
api.registerCommand('add', {
description: 'add a new page',
usage: 'vue-cli-service add [page]',
description: '创建一个新页面',
usage: 'vue-cli-service add [page]',
}, async function serve (args) {
info('Adding a new page...')
// entry arg
const entry = args._[0]
// api.resolve(dist + entry)
if (entry) {
copy(source, api.resolve(dist + entry), function(err, files) {
if (err) throw err;
// `files` is an array of the files that were copied
console.log(chalk.yellow(`页面${entry}创建成功!`))
});
} else {
console.log(chalk.red(`npm run add [page] 缺失参数: page`))
}
const entry = args._[0]
if(entry){
const entryPath = api.resolve(`./src/pages/${entry}`)
if( fs.existsSync(api.resolve(entryPath))){
console.log(chalk.red(`${entry}页面已存在,请重新填写页面!`))
return
}
inquirer
.prompt([
{
type: 'input',
name: 'name',
message: '请输入页面的中文名称(选填):'
}
])
.then(answers => {
if(answers.name){
copy(source, api.resolve(entryPath), function(err, files) {
if (err) throw err;
// 修改html
modifyFile(`${entryPath}/main.html`,{title:answers.name},'string')
modifyFile(`${entryPath}/main.ts`,{name:entry})
modifyFile(`${entryPath}/views/Main.vue`,{title:answers.name})
console.log(chalk.green(`页面${entry}创建成功!`))
});
}
});
} else {
console.log(chalk.red(`npm run add [page] 缺少页面参数: page`))
}
/**
* 修改文件
* @param {*} file
* @param {*} data
*/
function modifyFile(file,data,type){
if (fs.existsSync(file)) {
const content = fs.readFileSync(file).toString();
let result = content;
if(type==='string'){
for (const dataItem of Object.keys(data)) {
const reg = new RegExp(`{{${dataItem}}}`,'g')
result = result.replace(reg,`${data[dataItem]}`);
}
} else{
result = ejs.compile(content)(data);
}
fs.writeFileSync(file, result);
}
}
})
}
\ No newline at end of file
}
\ No newline at end of file
const glob = require('glob')
const fs=require('fs-extra')
const path = require('path')
const chalk = require('chalk')
const defaults = {
clean: true,
target: 'app',
......@@ -12,7 +14,7 @@ const buildModes = {
wc: 'web component',
'wc-async': 'web component (async)'
}
const allPages = fs.readdirSync(path.resolve('./src/pages/')).filter(page=>(page!=='.DS_Store' && page !=='common'))
const modifyConfig = (config, fn) => {
if (Array.isArray(config)) {
config.forEach(c => fn(c))
......@@ -20,7 +22,7 @@ const modifyConfig = (config, fn) => {
fn(config)
}
}
module.exports = (api, options) => {
api.registerCommand('build', {
description: 'build for production',
......@@ -45,53 +47,51 @@ module.exports = (api, options) => {
args[key] = defaults[key]
}
}
// 拿到所有页面
const allPages = glob.sync('./src/pages/*').map(m=>m.replace('./src/pages/', '').replace('/', '')).filter(item=> item!=='common');
const entry = args._[0]?args._[0].split('+'):''
let pages = []
if(entry && entry.length>0){
for (const item of entry) {
if(allPages.indexOf(item)>=0){
pages.push(item)
}
}
} else{
pages=allPages
}
pages.forEach(async item => {
if(!args._[0]){
console.log(chalk.red(`npm run build [page] 缺少页面参数: page`))
return
}
const pageData = getPages(args)
if(pageData.length===0){
console.log(chalk.red(`你所编译的页面不存在`))
return
}
pageData.forEach(async item=>{
args.entry = item
if (args.target !== 'app') {
args.entry = args.entry || 'src/App.vue'
}
process.env.VUE_CLI_BUILD_TARGET = args.target
if (args.modern && args.target === 'app') {
process.env.VUE_CLI_MODERN_MODE = true
if (!process.env.VUE_CLI_MODERN_BUILD) {
delete process.env.VUE_CLI_MODERN_BUILD
// if (!process.env.VUE_CLI_MODERN_BUILD) {
// main-process for legacy build
await build(Object.assign({}, args, {
modernBuild: false,
keepAlive: true
}), api, options)
// spawn sub-process of self for modern build
const { execa } = require('@vue/cli-shared-utils')
const cliBin = require('path').resolve(__dirname, '../../../bin/vue-cli-service.js')
await execa(cliBin, ['build', ...rawArgs], {
stdio: 'inherit',
env: {
VUE_CLI_MODERN_BUILD: true
}
})
} else {
// const { execa } = require('@vue/cli-shared-utils')
// const cliBin = require('@vue/cli-service/bin/vue-cli-service.js')
// await execa(cliBin, ['build', ...rawArgs], {
// stdio: 'inherit',
// env: {
// VUE_CLI_MODERN_BUILD: true
// }
// })
// } else {
process.env.VUE_CLI_MODERN_BUILD = true
// sub-process for modern build
await build(Object.assign({}, args, {
modernBuild: true,
clean: false
}), api, options)
}
// }
delete process.env.VUE_CLI_MODERN_MODE
delete process.env.VUE_CLI_MODERN_BUILD
} else {
if (args.modern) {
const { warn } = require('@vue/cli-shared-utils')
......@@ -104,13 +104,27 @@ module.exports = (api, options) => {
await build(args, api, options)
}
delete process.env.VUE_CLI_BUILD_TARGET
})
})
})
}
/**
* 获取页面
* @param {Array} args
*/
function getPages(args) {
let pages = []
if(args._[0]){
args._[0].split('+').forEach(item=>{
if(allPages.indexOf(item)>=0){
pages.push(item)
}
})
}
return pages
}
async function build (args, api, options) {
const fs = require('fs-extra')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const formatStats = require('../util/formatStats')
......@@ -148,30 +162,49 @@ async function build (args, api, options) {
// resolve raw webpack config
let webpackConfig
if (args.target === 'lib') {
webpackConfig = require('./resolveLibConfig')(api, args, options)
webpackConfig = require('../util/resolveLibConfig')(api, args, options)
} else if (
args.target === 'wc' ||
args.target === 'wc-async'
) {
webpackConfig = require('./resolveWcConfig')(api, args, options)
webpackConfig = require('../util/resolveWcConfig')(api, args, options)
} else {
webpackConfig = require('../util/resolveAppConfig')(api, args, options)
}
// check for common config errors
validateWebpackConfig(webpackConfig, api, options, args.target)
// 获取页眉页脚
const headerPath = path.resolve('./src/pages/common/header.html')
const footerPath = path.resolve('./src/pages/common/footer.html')
const headerTpl = fs.existsSync(headerPath)?fs.readFileSync(headerPath):''
const footerTpl = fs.existsSync(footerPath)?fs.readFileSync(footerPath):''
const entry = args.entry // 1
const entry = args.entry
if (entry) {
const pagesPath = "./src/pages/" + entry // 1,增加模块路径
webpackConfig.entry = {
// app: api.resolve(entry)
app: pagesPath + '/main' // 2,修改entry入口
}
const pagePath = "./src/pages/" + entry
webpackConfig.entry={}
webpackConfig.entry[entry] = pagePath + '/main.ts'
webpackConfig.output.publicPath = ''
webpackConfig.output.path = targetDir
for(let item of webpackConfig.plugins) {
if (item.options && item.options.template) item.options.template= pagesPath + '/main.html' // 3,修改webpackConfig.plugins.HtmlWebpackPlugin template 入口
if (item.options && item.options.template) {
item.options.template= pagePath + '/main.html'
item.options.header = headerTpl
item.options.footer = footerTpl
}
}
for (let item of webpackConfig.module.rules) {
if(item.test.toString().indexOf('png|jp')>=0){
for (const itemChild of item.use) {
if(itemChild.options){
itemChild.options.publicPath = itemChild.options.publicPath.indexOf(entry)<0?itemChild.options.publicPath+'/'+entry:itemChild.options.publicPath
break
}
}
break
}
}
}
......@@ -191,7 +224,7 @@ async function build (args, api, options) {
// Expose advanced stats
if (args.dashboard) {
const DashboardPlugin = require('../../webpack/DashboardPlugin')
const DashboardPlugin = require('@vue/cli-service/lib/webpack/DashboardPlugin')
modifyConfig(webpackConfig, config => {
config.plugins.push(new DashboardPlugin({
type: 'build',
......@@ -219,7 +252,7 @@ async function build (args, api, options) {
}
if (args.clean) {
await fs.remove(targetDir)
await fs.remove(api.resolve(args.dest || options.outputDir))
}
return new Promise((resolve, reject) => {
......@@ -262,3 +295,4 @@ async function build (args, api, options) {
module.exports.defaultModes = {
build: 'production'
}
\ No newline at end of file
This diff is collapsed.
module.exports = (api, options, rootOptions) => {
// 修改 `package.json` 里的字段
module.exports=(api,opts)=>{
api.extendPackage({
scripts: {
start: 'vue-cli-service serve',
build: 'vue-cli-service build',
add: 'vue-cli-service add'
}
scripts: {
add: 'vue-cli-service add',
},
devDependencies:{
"inquirer": "^7.0.0",
"copy": "^0.3.2",
},
})
// 复制并用 ejs 渲染 `./template` 内所有的文件
api.render('./template', {
doesCompile: api.hasPlugin('babel') || api.hasPlugin('typescript')
})
// if (options.foo) {
// // 有条件地生成文件
// }
// 根据eslint配置自动校正
api.onCreateComplete(() => {
// Linting the generated files
if (api.hasPlugin('eslint')) {
// Lint generated/modified files
try {
const lint = require('@vue/cli-plugin-eslint/lint')
lint({ silent: true }, api)
} catch (e) {
// No ESLint vue-cli plugin
}
}
})
}
\ No newline at end of file
}
\ No newline at end of file
<%_ if (!rootOptions.router) { _%>
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<%_ if (!rootOptions.bare) { _%>
<HelloWorld msg="Welcome to Your Vue.js App"/>
<%_ } else { _%>
<h1>Welcome to Your Vue.js App</h1>
<%_ } _%>
</div>
</template>
<%_ if (!rootOptions.bare) { _%>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<%_ } _%>
<%_ } else { _%>
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<%_ } _%>
<%_ if (!rootOptions.bare) { _%>
<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
<style<%-
rootOptions.cssPreprocessor
? ` lang="${
rootOptions.cssPreprocessor === 'sass'
? 'scss'
: rootOptions.cssPreprocessor
}"`
: ``
%>>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
<%_ if (!rootOptions.router) { _%>
margin-top: 60px;
<%_ } _%>
}
<%_ if (rootOptions.router) { _%>
<%_ if (!rootOptions.cssPreprocessor) { _%>
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
<%_ } else { _%>
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
<%_ } _%>
<%_ } _%>
</style>
<%_ } else { _%>
<style lang="stylus">
#app
font-family 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50
<%_ if (!rootOptions.router) { _%>
margin-top 60px
<%_ } _%>
<%_ if (rootOptions.router) { _%>
#nav
padding 30px
a
font-weight bold
color #2c3e50
&.router-link-exact-active
color #42b983
<%_ } _%>
</style>
<%_ } _%>
<%_ } _%>
<%_ if (!rootOptions.bare) { _%>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<%_ for (plugin of plugins) { _%>
<li><a href="<%- plugin.link %>" target="_blank" rel="noopener"><%- plugin.name %></a></li>
<%_ } _%>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
<style scoped<%-
rootOptions.cssPreprocessor
? ` lang="${
rootOptions.cssPreprocessor === 'sass'
? 'scss'
: rootOptions.cssPreprocessor
}"`
: ``
%>>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<%_ } else { _%>
<style scoped lang="stylus">
h3
margin 40px 0 0
ul
list-style-type none
padding 0
li
display inline-block
margin 0 10px
a
color #42b983
</style>
<%_ } _%>
<%_ } _%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%%= BASE_URL %%>favicon.ico">
<title><%= rootOptions.projectName %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= rootOptions.projectName %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
<%_ if (doesCompile) { _%>
render: h => h(App),
<%_ } else { _%>
render: function (h) { return h(App) },
<%_ } _%>
}).$mount('#app')
......@@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<%= htmlWebpackPlugin.options.header %>
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>标题</title>
<title>{{title}}</title>
<script>
</script>
</head>
......
......@@ -5,13 +5,15 @@ import VueAxios from 'vue-axios';
import '@/utils/common';
const win = window as any;
// 全局设置cors cookie
axios.defaults.withCredentials = true;
axios.defaults.headers['Content-Type'] = 'application/json';
Vue.use(VueAxios, axios);
// 阻止启动生产消息
Vue.config.productionTip = false;
new Vue({
name: 'module',
name: '<%= name %>',
components: {
Main,
},
......
<template>
<div>
<HeaderBar>title</HeaderBar>
<div class="container">
<HeaderBar><%= title %></HeaderBar>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import HeaderBar from '@/components/headerBar/index.vue';
@Component({
components: {
HeaderBar,
},
})
export default class Home extends Vue {
export default class Main extends Vue {
// 生命周期钩子
public created() {
console.log('created')
}
private mounted() {
console.log('mounted')
}
}
</script>
......
const add = require('./commands/add')
const build = require('./commands/build')
const serve = require('./commands/serve')
const add = require('./commands/add')
module.exports = (api, opts) => {
const serve = require('./commands/serve')
module.exports = (api, opts) =>{
add(api, opts)
build(api, opts)
serve(api,opts)
add(api,opts)
serve(api, opts)
}
\ No newline at end of file
{
"name": "vue-cli-plugin-multi-pages",
"version": "1.0.0",
"description": "",
"version": "1.1.3",
"description": "vue-cli3多页开发插件",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"copy": "^0.3.2"
}
}
\ No newline at end of file
"keywords": [],
"author": "shangbj",
"license": "ISC"
}
......@@ -4,7 +4,6 @@ module.exports = function formatStats (stats, dir, api) {
const zlib = require('zlib')
const chalk = require('chalk')
const ui = require('cliui')({ width: 80 })
const url = require('url');
const json = stats.toJson({
hash: false,
......@@ -21,10 +20,6 @@ module.exports = function formatStats (stats, dir, api) {
const isCSS = val => /\.css$/.test(val)
const isMinJS = val => /\.min\.js$/.test(val)
assets = assets
.map(a => {
a.name = url.parse(a.name).pathname
return a
})
.filter(a => {
if (seenNames.has(a.name)) {
return false
......
const path = require('path')
module.exports = function getAssetPath (options, filePath) {
return options.assetsDir
? path.posix.join(options.assetsDir, filePath)
: filePath
}
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
......@@ -31,7 +31,7 @@ module.exports = (api, args, options) => {
unsafeInline: args['unsafe-inline'],
// as we may generate an addition file asset (if `no-unsafe-inline` specified)
// we need to provide the correct directory for that file to place in
jsDirectory: require('vue-cli-plugin-multi-pages/util/getAssetPath')(options, 'js')
jsDirectory: require('../../util/getAssetPath')(options, 'js')
}])
}
}
......@@ -42,6 +42,7 @@ module.exports = (api, args, options) => {
if (args.entry && !options.pages) {
rawConfig.entry = { app: api.resolve(args.entry) }
}
return rawConfig
}
\ No newline at end of file
const fs = require('fs')
const path = require('path')
module.exports = (api, { entry, name, formats, filename }, options) => {
const { log, error } = require('@vue/cli-shared-utils')
const abort = msg => {
log()
error(msg)
process.exit(1)
}
const fullEntryPath = api.resolve(entry)
if (!fs.existsSync(fullEntryPath)) {
abort(
`Failed to resolve lib entry: ${entry}${entry === `src/App.vue` ? ' (default)' : ''}. ` +
`Make sure to specify the correct entry file.`
)
}
const isVueEntry = /\.vue$/.test(entry)
const libName = (
name ||
api.service.pkg.name ||
path.basename(entry).replace(/\.(jsx?|vue)$/, '')
)
filename = filename || libName
function genConfig (format, postfix = format, genHTML) {
const config = api.resolveChainableWebpackConfig()
const browserslist = require('browserslist')
const targets = browserslist(undefined, { path: fullEntryPath })
const supportsIE = targets.some(agent => agent.includes('ie'))
const webpack = require('webpack')
config.plugin('need-current-script-polyfill')
.use(webpack.DefinePlugin, [{
'process.env.NEED_CURRENTSCRIPT_POLYFILL': JSON.stringify(supportsIE)
}])
// adjust css output name so they write to the same file
if (config.plugins.has('extract-css')) {
config
.plugin('extract-css')
.tap(args => {
args[0].filename = `${filename}.css`
return args
})
}
// only minify min entry
if (!/\.min/.test(postfix)) {
config.optimization.minimize(false)
}
// externalize Vue in case user imports it
config
.externals({
...config.get('externals'),
vue: {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
}
})
// inject demo page for umd
if (genHTML) {
const template = isVueEntry ? 'demo-lib.html' : 'demo-lib-js.html'
config
.plugin('demo-html')
.use(require('html-webpack-plugin'), [{
template: path.resolve(__dirname, template),
inject: false,
filename: 'demo.html',
libName,
assetsFileName: filename,
cssExtract: config.plugins.has('extract-css')
}])
}
// resolve entry/output
const entryName = `${filename}.${postfix}`
config.resolve
.alias
.set('~entry', fullEntryPath)
// set output target before user configureWebpack hooks are applied
config.output.libraryTarget(format)
// set entry/output after user configureWebpack hooks are applied
const rawConfig = api.resolveWebpackConfig(config)
let realEntry = require.resolve('./entry-lib.js')
// avoid importing default if user entry file does not have default export
if (!isVueEntry) {
const entryContent = fs.readFileSync(fullEntryPath, 'utf-8')
if (!/\b(export\s+default|export\s{[^}]+as\s+default)\b/.test(entryContent)) {
realEntry = require.resolve('./entry-lib-no-default.js')
}
}
rawConfig.entry = {
[entryName]: realEntry
}
rawConfig.output = Object.assign({
library: libName,
libraryExport: isVueEntry ? 'default' : undefined,
libraryTarget: format,
// preserve UDM header from webpack 3 until webpack provides either
// libraryTarget: 'esm' or target: 'universal'
// https://github.com/webpack/webpack/issues/6522
// https://github.com/webpack/webpack/issues/6525
globalObject: `(typeof self !== 'undefined' ? self : this)`
}, rawConfig.output, {
filename: `${entryName}.js`,
chunkFilename: `${entryName}.[name].js`,
// use dynamic publicPath so this can be deployed anywhere
// the actual path will be determined at runtime by checking
// document.currentScript.src.
publicPath: ''
})
return rawConfig
}
const configMap = {
commonjs: genConfig('commonjs2', 'common'),
umd: genConfig('umd', undefined, true),
'umd-min': genConfig('umd', 'umd.min')
}
const formatArray = (formats + '').split(',')
const configs = formatArray.map(format => configMap[format])
if (configs.indexOf(undefined) !== -1) {
const unknownFormats = formatArray.filter(f => configMap[f] === undefined).join(', ')
abort(
`Unknown library build formats: ${unknownFormats}`
)
}
return configs
}
const path = require('path')
const { resolveEntry, fileToComponentName } = require('./resolveWcEntry')
module.exports = (api, { target, entry, name }) => {
// Disable CSS extraction and turn on CSS shadow mode for vue-style-loader
process.env.VUE_CLI_CSS_SHADOW_MODE = true
const { log, error } = require('@vue/cli-shared-utils')
const abort = msg => {
log()
error(msg)
process.exit(1)
}
const isAsync = /async/.test(target)
// generate dynamic entry based on glob files
const resolvedFiles = require('globby').sync([entry], { cwd: api.resolve('.') })
if (!resolvedFiles.length) {
abort(`entry pattern "${entry}" did not match any files.`)
}
let libName
let prefix
if (resolvedFiles.length === 1) {
// in single mode, determine the lib name from filename
libName = name || fileToComponentName('', resolvedFiles[0]).kebabName
prefix = ''
if (libName.indexOf('-') < 0) {
abort(`--name must contain a hyphen when building a single web component.`)
}
} else {
// multi mode
libName = prefix = (name || api.service.pkg.name)
if (!libName) {
abort(`--name is required when building multiple web components.`)
}
}
const dynamicEntry = resolveEntry(prefix, libName, resolvedFiles, isAsync)
function genConfig (minify, genHTML) {
const config = api.resolveChainableWebpackConfig()
// make sure not to transpile wc-wrapper
config.module
.rule('js')
.exclude
.add(/vue-wc-wrapper/)
// only minify min entry
if (!minify) {
config.optimization.minimize(false)
}
// externalize Vue in case user imports it
config
.externals({
...config.get('externals'),
vue: 'Vue'
})
config
.plugin('web-component-options')
.use(require('webpack/lib/DefinePlugin'), [{
'process.env': {
CUSTOM_ELEMENT_NAME: JSON.stringify(libName)
}
}])
// enable shadow mode in vue-loader
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.shadowMode = true
return options
})
if (genHTML) {
config
.plugin('demo-html')
.use(require('html-webpack-plugin'), [{
template: path.resolve(__dirname, `./demo-wc.html`),
inject: false,
filename: 'demo.html',
libName,
components:
prefix === ''
? [libName]
: resolvedFiles.map(file => {
return fileToComponentName(prefix, file).kebabName
})
}])
}
// set entry/output last so it takes higher priority than user
// configureWebpack hooks
// set proxy entry for *.vue files
config.resolve
.alias
.set('~root', api.resolve('.'))
const rawConfig = api.resolveWebpackConfig(config)
const entryName = `${libName}${minify ? `.min` : ``}`
rawConfig.entry = {
[entryName]: dynamicEntry
}
Object.assign(rawConfig.output, {
// to ensure that multiple copies of async wc bundles can co-exist
// on the same page.
jsonpFunction: libName.replace(/-\w/g, c => c.charAt(1).toUpperCase()) + '_jsonp',
filename: `${entryName}.js`,
chunkFilename: `${libName}.[name]${minify ? `.min` : ``}.js`,
// use dynamic publicPath so this can be deployed anywhere
// the actual path will be determined at runtime by checking
// document.currentScript.src.
publicPath: ''
})
return rawConfig
}
return [
genConfig(false, true),
genConfig(true, false)
]
}
File mode changed from 100644 to 100755
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