В большинстве случаев мы используемwebpack
Чтобы упаковать одностраничное приложение, вам нужно настроить только одну запись и один файл шаблона в это время, но это не тот случай, иногда вы столкнетесь с многостраничными проектами, и по моему опыту, такая ситуация встречается. не является низким.Например, проект относительно большой и не может быть понят в целом, или проект требует нескольких итераций обновления и т. д., все из которых подходят для создания многостраничных программ, которые включаютwebpack
Проблема конфигурации упаковки многостраничного файла.
Ручная настройка
Одностраничные приложения и многостраничные приложенияwebpack
На самом деле, большинство файлов конфигурации все те же, но конфигурация нескольких страниц должна учитывать несколько страниц на основе одностраничной конфигурации.loader
,output
,plugins
В основном их не нужно изменять, а файлы ввода, которые необходимо изменить, обычно являются файлами ввода.entry
, если вы использовалиcss
плагин стиляextract-text-webpack-plugin
, плагин автоматического шаблонаhtml-webpack-plugin
Если да, то требуется дополнительная переписывание этих двух плагинов.В большинстве случаев нам нужно изменить только эти три места, поэтому в этой статье будет кратко рассказано только об этих трех местах.Есть и другие места, которые нужно изменить , просто обратитесь к этим трем позициям.
Пример каталога файлов выглядит следующим образом:
entry
Конфигурация входа одностраничного приложения обычно выглядит следующим образом:
entry: resolve(__dirname, "src/home/index.js")
Эта конфигурация должна указатьwebpack
от/src/home/index.js
Этот файл начинает поступать, и выполняется ряд процессов упаковки и компиляции.
Если это многостраничное приложение, требуется несколько входных файлов, например:
entry: {
home: resolve(__dirname, "src/home/index.js"),
about: resolve(__dirname, "src/about/index.js")
}
Таким образом, весь проект имеет два входа.home
иabout
extract-text-webpack-plugin
extract-text-webpack-plugin
Плагин предназначен в основном для извлеченияcss
стили, предотвращая упаковку стилей вjs
вызвать нарушение загрузки стиля страницы илиjs
Если размер сценария слишком велик, в одностраничной программе этот плагин обычно используется следующим образом:
plugins: [
new ExtractTextPlugin('style.[contenthash].css')
]
В многостраничной программе из-за наличия нескольких входных файлов и соответствующих нескольких страниц каждая страница имеет свой собственныйcss
style, поэтому вам нужно настроить его для каждой страницы:
plugins: [
new ExtractTextPlugin('home/[name].[contenthash].css'),
new ExtractTextPlugin('about/[name].[contenthash].css')
]
В дополнение к этому следует отметить, что каждая страница нуждается только в своемcss
стиль, теоретически поставить другие страницыcss
Можно конечно упаковать файл стилей в свою страницу, но это явно неразумно.Это только увеличит избыточный код, а также может привести к таким проблемам, как непредсказуемое покрытие стиля.Поэтому необходимоloader
Измените конфигурацию:
{
test: /\.css$/,
loader: 'style!css!autoprefixer'
},
{
test: /\.scss$/,
loaders: [
'style',
'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'sass',
'autoprefixer'
]
},
Приведенная выше конфигурация скомпилирует всеcss
файлы в тот же файл, все, что нам нужно сделать, это поместить этиcss
отдельно, каждая страница имеет свой отдельныйcss
файл стиля:
// 为每个页面定义一个 ExtractTextPlugin
const homeExtractCss = new ExtractTextPlugin('home/[name].[contenthash].css')
const aboutExtractCss = new ExtractTextPlugin('about/[name].[contenthash].css')
// ...
module: {
rules: [
// 每个页面的 ExtractTextPlugin 只处理这个页面的样式文件
{
test: /src(\\|\/)home(\\|\/)css(\\|\/).*\.(css|scss)$/,
use: homePageExtractCss.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'sass-loader']
})
},
{
test: /src(\\|\/)about(\\|\/)css(\\|\/).*\.(css|scss)$/,
use: salePersonalCenterExtractCss.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'sass-loader']
})
}
]
}
// ...
// 每个页面都有各自的 ExtractTextPlugin,所以需要都声明一遍
plugins: [
homeExtractCss,
aboutExtractCss
]
html-webpack-plugin
html-webpack-plugin
Использование плагинов в одностраничных и многостраничных приложенияхwebpack
Конфигурация не имеет значения
new HtmlWebpackPlugin({
filename: 'home/home.html',
template: 'src/home/html/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true
}
})
new HtmlWebpackPlugin({
filename: 'about/about.html',
template: 'src/about/html/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true
}
})
Если страниц несколько, вы можете выполнить описанную выше настройку на каждой странице.
Автоматическая конфигурация
Приведенный выше код конфигурации уже может удовлетворить потребности многостраничной разработки, но выглядит несколько прискорбно, то есть каждый раз при добавлении страницы ее нужно снова обновлятьentry
,extract-text-webpack-plugin
,HtmlWebpackPlugin
конфигурации, хотя дело всего в нескольких строчках кода, и в принципе скопировать и вставить несложно, но ведь как бы ни был мал код, его все равно нужно задавать, а мест много что нужно изменить, что можно пропустить в спешке, если это можно сделать раз и навсегда, Напишите код один раз, и вам не нужно будет спрашивать, добавляете ли вы или удаляете страницы в дальнейшем.
Небольшое наблюдение за этим каталогом показывает, что структура каталогов на самом деле очень регулярна:
Каждая страницаsrc/
Папка в каталоге.В этой папке есть два подкаталога, в которых соответственно хранятся шаблоны этой страницы.html
, файл стиляcss
, и входной файлindex.js
Поскольку существуют правила, должна существовать возможность программирования кода.Если следовать этому правилу, каждая страница./src
В следующем каталоге имя каталога является именем страницы, и структура в этом каталоге такая же, тогда вы можете получить все имена страниц с помощью общего метода (например,home
,about
), пример этого универсального метода выглядит следующим образом:
function getEntry () {
let globPath = 'src/**/html/*.html'
// (\/|\\\\) 这种写法是为了兼容 windows和 mac系统目录路径的不同写法
let pathDir = 'src(\/|\\\\)(.*?)(\/|\\\\)html'
let files = glob.sync(globPath)
let dirname, entries = []
for (let i = 0; i < files.length; i++) {
dirname = path.dirname(files[i])
entries.push(dirname.replace(new RegExp('^' + pathDir), '$2'))
}
return entries
}
с помощьюglobэта библиотека, траверс.src/
В каталоге есть это правилоsrc/**/html/*.html
подкаталог, имя этого подкаталога получается путем обычного сопоставления
Получите все имена страниц, это легко сделать.
entry
// entry: resolve(__dirname, "src/home/index.js")
// 改为
entry: addEntry()
//...
function addEntry () {
let entryObj = {}
getEntry().forEach(item => {
entryObj[item] = resolve(__dirname, 'src', item, 'index.js')
})
return entryObj
}
extract-text-webpack-plugin
// plugins: [
// new ExtractTextPlugin('home/[name].[contenthash].css'),
// new ExtractTextPlugin('about/[name].[contenthash].css')
//]
// 改为
const pageExtractCssArray = []
getEntry().forEach(item => {
pageExtractCssArray.push(new ExtractTextPlugin(item + '/[name].[contenthash].css'))
})
// ...
plugins: [...pageExtractCssArray]
module.rules
два стиляloaders
Удалите его и добавьте вместо этого динамически:
getEntry().forEach((item, i) => {
webpackconfig.module.rules.push({
test: new RegExp('src' + '(\\\\|\/)' + item + '(\\\\|\/)' + 'css' + '(\\\\|\/)' + '.*\.(css|scss)$'),
use: pageExtractCssArray[i].extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'sass-loader']
})
})
})
// ...
module.exports = webpackconfig
html-webpack-plugin
plugins
без ручной инициализацииhtml-webpack-plugin
, вместо этого добавьте динамически:
getEntry().forEach(pathname => {
let conf = {
filename: path.join(pathname, pathname) + '.html',
template: path.join(__dirname, 'src', pathname, 'html', 'index.html')
}
webpackconfig.plugins.push(new HtmlWebpackPlugin(conf))
})
// ...
module.exports = webpackconfig
После выполнения вышеуказанной модификации, независимо от того, добавляете ли вы или удаляете страницы в проекте, вам не нужноwebpack
Конфигурация была изменена вручную.Хотя поначалу кажется, что этот код динамической автоматической конфигурации становится все более и более сложным, в конечном итоге это, безусловно, хорошая практика раз и навсегда.
Кроме того, если структура каталогов вашего проекта отличается от структуры каталогов моего примера, вам необходимо внести небольшие изменения в код в соответствии с вашей собственной структурой каталогов, но общее решение проблемы такое же, простое. для поддержания проекта, структура каталогов должна быть дисциплинированной.